diff options
Diffstat (limited to 'tools/perf/tests')
38 files changed, 4182 insertions, 0 deletions
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c new file mode 100644 index 000000000000..6e2feee8db2a --- /dev/null +++ b/tools/perf/tests/attr.c | |||
@@ -0,0 +1,174 @@ | |||
1 | |||
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 <stdlib.h> | ||
23 | #include <stdio.h> | ||
24 | #include <inttypes.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include "../perf.h" | ||
28 | #include "util.h" | ||
29 | #include "exec_cmd.h" | ||
30 | |||
31 | #define ENV "PERF_TEST_ATTR" | ||
32 | |||
33 | extern int verbose; | ||
34 | |||
35 | bool test_attr__enabled; | ||
36 | |||
37 | static char *dir; | ||
38 | |||
39 | void test_attr__init(void) | ||
40 | { | ||
41 | dir = getenv(ENV); | ||
42 | test_attr__enabled = (dir != NULL); | ||
43 | } | ||
44 | |||
45 | #define BUFSIZE 1024 | ||
46 | |||
47 | #define __WRITE_ASS(str, fmt, data) \ | ||
48 | do { \ | ||
49 | char buf[BUFSIZE]; \ | ||
50 | size_t size; \ | ||
51 | \ | ||
52 | size = snprintf(buf, BUFSIZE, #str "=%"fmt "\n", data); \ | ||
53 | if (1 != fwrite(buf, size, 1, file)) { \ | ||
54 | perror("test attr - failed to write event file"); \ | ||
55 | fclose(file); \ | ||
56 | return -1; \ | ||
57 | } \ | ||
58 | \ | ||
59 | } while (0) | ||
60 | |||
61 | #define WRITE_ASS(field, fmt) __WRITE_ASS(field, fmt, attr->field) | ||
62 | |||
63 | static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu, | ||
64 | int fd, int group_fd, unsigned long flags) | ||
65 | { | ||
66 | FILE *file; | ||
67 | char path[PATH_MAX]; | ||
68 | |||
69 | snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir, | ||
70 | attr->type, attr->config, fd); | ||
71 | |||
72 | file = fopen(path, "w+"); | ||
73 | if (!file) { | ||
74 | perror("test attr - failed to open event file"); | ||
75 | return -1; | ||
76 | } | ||
77 | |||
78 | if (fprintf(file, "[event-%d-%llu-%d]\n", | ||
79 | attr->type, attr->config, fd) < 0) { | ||
80 | perror("test attr - failed to write event file"); | ||
81 | fclose(file); | ||
82 | return -1; | ||
83 | } | ||
84 | |||
85 | /* syscall arguments */ | ||
86 | __WRITE_ASS(fd, "d", fd); | ||
87 | __WRITE_ASS(group_fd, "d", group_fd); | ||
88 | __WRITE_ASS(cpu, "d", cpu); | ||
89 | __WRITE_ASS(pid, "d", pid); | ||
90 | __WRITE_ASS(flags, "lu", flags); | ||
91 | |||
92 | /* struct perf_event_attr */ | ||
93 | WRITE_ASS(type, PRIu32); | ||
94 | WRITE_ASS(size, PRIu32); | ||
95 | WRITE_ASS(config, "llu"); | ||
96 | WRITE_ASS(sample_period, "llu"); | ||
97 | WRITE_ASS(sample_type, "llu"); | ||
98 | WRITE_ASS(read_format, "llu"); | ||
99 | WRITE_ASS(disabled, "d"); | ||
100 | WRITE_ASS(inherit, "d"); | ||
101 | WRITE_ASS(pinned, "d"); | ||
102 | WRITE_ASS(exclusive, "d"); | ||
103 | WRITE_ASS(exclude_user, "d"); | ||
104 | WRITE_ASS(exclude_kernel, "d"); | ||
105 | WRITE_ASS(exclude_hv, "d"); | ||
106 | WRITE_ASS(exclude_idle, "d"); | ||
107 | WRITE_ASS(mmap, "d"); | ||
108 | WRITE_ASS(comm, "d"); | ||
109 | WRITE_ASS(freq, "d"); | ||
110 | WRITE_ASS(inherit_stat, "d"); | ||
111 | WRITE_ASS(enable_on_exec, "d"); | ||
112 | WRITE_ASS(task, "d"); | ||
113 | WRITE_ASS(watermark, "d"); | ||
114 | WRITE_ASS(precise_ip, "d"); | ||
115 | WRITE_ASS(mmap_data, "d"); | ||
116 | WRITE_ASS(sample_id_all, "d"); | ||
117 | WRITE_ASS(exclude_host, "d"); | ||
118 | WRITE_ASS(exclude_guest, "d"); | ||
119 | WRITE_ASS(exclude_callchain_kernel, "d"); | ||
120 | WRITE_ASS(exclude_callchain_user, "d"); | ||
121 | WRITE_ASS(wakeup_events, PRIu32); | ||
122 | WRITE_ASS(bp_type, PRIu32); | ||
123 | WRITE_ASS(config1, "llu"); | ||
124 | WRITE_ASS(config2, "llu"); | ||
125 | WRITE_ASS(branch_sample_type, "llu"); | ||
126 | WRITE_ASS(sample_regs_user, "llu"); | ||
127 | WRITE_ASS(sample_stack_user, PRIu32); | ||
128 | |||
129 | fclose(file); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, | ||
134 | int fd, int group_fd, unsigned long flags) | ||
135 | { | ||
136 | int errno_saved = errno; | ||
137 | |||
138 | if (store_event(attr, pid, cpu, fd, group_fd, flags)) | ||
139 | die("test attr FAILED"); | ||
140 | |||
141 | errno = errno_saved; | ||
142 | } | ||
143 | |||
144 | static int run_dir(const char *d, const char *perf) | ||
145 | { | ||
146 | char cmd[3*PATH_MAX]; | ||
147 | |||
148 | snprintf(cmd, 3*PATH_MAX, "python %s/attr.py -d %s/attr/ -p %s %s", | ||
149 | d, d, perf, verbose ? "-v" : ""); | ||
150 | |||
151 | return system(cmd); | ||
152 | } | ||
153 | |||
154 | int test_attr__run(void) | ||
155 | { | ||
156 | struct stat st; | ||
157 | char path_perf[PATH_MAX]; | ||
158 | char path_dir[PATH_MAX]; | ||
159 | |||
160 | /* First try developement tree tests. */ | ||
161 | if (!lstat("./tests", &st)) | ||
162 | return run_dir("./tests", "./perf"); | ||
163 | |||
164 | /* Then installed path. */ | ||
165 | snprintf(path_dir, PATH_MAX, "%s/tests", perf_exec_path()); | ||
166 | snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR); | ||
167 | |||
168 | if (!lstat(path_dir, &st) && | ||
169 | !lstat(path_perf, &st)) | ||
170 | return run_dir(path_dir, path_perf); | ||
171 | |||
172 | fprintf(stderr, " (ommitted)"); | ||
173 | return 0; | ||
174 | } | ||
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py new file mode 100644 index 000000000000..e702b82dcb86 --- /dev/null +++ b/tools/perf/tests/attr.py | |||
@@ -0,0 +1,322 @@ | |||
1 | #! /usr/bin/python | ||
2 | |||
3 | import os | ||
4 | import sys | ||
5 | import glob | ||
6 | import optparse | ||
7 | import tempfile | ||
8 | import logging | ||
9 | import shutil | ||
10 | import ConfigParser | ||
11 | |||
12 | class Fail(Exception): | ||
13 | def __init__(self, test, msg): | ||
14 | self.msg = msg | ||
15 | self.test = test | ||
16 | def getMsg(self): | ||
17 | return '\'%s\' - %s' % (self.test.path, self.msg) | ||
18 | |||
19 | class Unsup(Exception): | ||
20 | def __init__(self, test): | ||
21 | self.test = test | ||
22 | def getMsg(self): | ||
23 | return '\'%s\'' % self.test.path | ||
24 | |||
25 | class Event(dict): | ||
26 | terms = [ | ||
27 | 'flags', | ||
28 | 'type', | ||
29 | 'size', | ||
30 | 'config', | ||
31 | 'sample_period', | ||
32 | 'sample_type', | ||
33 | 'read_format', | ||
34 | 'disabled', | ||
35 | 'inherit', | ||
36 | 'pinned', | ||
37 | 'exclusive', | ||
38 | 'exclude_user', | ||
39 | 'exclude_kernel', | ||
40 | 'exclude_hv', | ||
41 | 'exclude_idle', | ||
42 | 'mmap', | ||
43 | 'comm', | ||
44 | 'freq', | ||
45 | 'inherit_stat', | ||
46 | 'enable_on_exec', | ||
47 | 'task', | ||
48 | 'watermark', | ||
49 | 'precise_ip', | ||
50 | 'mmap_data', | ||
51 | 'sample_id_all', | ||
52 | 'exclude_host', | ||
53 | 'exclude_guest', | ||
54 | 'exclude_callchain_kernel', | ||
55 | 'exclude_callchain_user', | ||
56 | 'wakeup_events', | ||
57 | 'bp_type', | ||
58 | 'config1', | ||
59 | 'config2', | ||
60 | 'branch_sample_type', | ||
61 | 'sample_regs_user', | ||
62 | 'sample_stack_user', | ||
63 | ] | ||
64 | |||
65 | def add(self, data): | ||
66 | for key, val in data: | ||
67 | log.debug(" %s = %s" % (key, val)) | ||
68 | self[key] = val | ||
69 | |||
70 | def __init__(self, name, data, base): | ||
71 | log.info(" Event %s" % name); | ||
72 | self.name = name; | ||
73 | self.group = '' | ||
74 | self.add(base) | ||
75 | self.add(data) | ||
76 | |||
77 | def compare_data(self, a, b): | ||
78 | # Allow multiple values in assignment separated by '|' | ||
79 | a_list = a.split('|') | ||
80 | b_list = b.split('|') | ||
81 | |||
82 | for a_item in a_list: | ||
83 | for b_item in b_list: | ||
84 | if (a_item == b_item): | ||
85 | return True | ||
86 | elif (a_item == '*') or (b_item == '*'): | ||
87 | return True | ||
88 | |||
89 | return False | ||
90 | |||
91 | def equal(self, other): | ||
92 | for t in Event.terms: | ||
93 | log.debug(" [%s] %s %s" % (t, self[t], other[t])); | ||
94 | if not self.has_key(t) or not other.has_key(t): | ||
95 | return False | ||
96 | if not self.compare_data(self[t], other[t]): | ||
97 | return False | ||
98 | return True | ||
99 | |||
100 | # Test file description needs to have following sections: | ||
101 | # [config] | ||
102 | # - just single instance in file | ||
103 | # - needs to specify: | ||
104 | # 'command' - perf command name | ||
105 | # 'args' - special command arguments | ||
106 | # 'ret' - expected command return value (0 by default) | ||
107 | # | ||
108 | # [eventX:base] | ||
109 | # - one or multiple instances in file | ||
110 | # - expected values assignments | ||
111 | class Test(object): | ||
112 | def __init__(self, path, options): | ||
113 | parser = ConfigParser.SafeConfigParser() | ||
114 | parser.read(path) | ||
115 | |||
116 | log.warning("running '%s'" % path) | ||
117 | |||
118 | self.path = path | ||
119 | self.test_dir = options.test_dir | ||
120 | self.perf = options.perf | ||
121 | self.command = parser.get('config', 'command') | ||
122 | self.args = parser.get('config', 'args') | ||
123 | |||
124 | try: | ||
125 | self.ret = parser.get('config', 'ret') | ||
126 | except: | ||
127 | self.ret = 0 | ||
128 | |||
129 | self.expect = {} | ||
130 | self.result = {} | ||
131 | log.info(" loading expected events"); | ||
132 | self.load_events(path, self.expect) | ||
133 | |||
134 | def is_event(self, name): | ||
135 | if name.find("event") == -1: | ||
136 | return False | ||
137 | else: | ||
138 | return True | ||
139 | |||
140 | def load_events(self, path, events): | ||
141 | parser_event = ConfigParser.SafeConfigParser() | ||
142 | parser_event.read(path) | ||
143 | |||
144 | # The event record section header contains 'event' word, | ||
145 | # optionaly followed by ':' allowing to load 'parent | ||
146 | # event' first as a base | ||
147 | for section in filter(self.is_event, parser_event.sections()): | ||
148 | |||
149 | parser_items = parser_event.items(section); | ||
150 | base_items = {} | ||
151 | |||
152 | # Read parent event if there's any | ||
153 | if (':' in section): | ||
154 | base = section[section.index(':') + 1:] | ||
155 | parser_base = ConfigParser.SafeConfigParser() | ||
156 | parser_base.read(self.test_dir + '/' + base) | ||
157 | base_items = parser_base.items('event') | ||
158 | |||
159 | e = Event(section, parser_items, base_items) | ||
160 | events[section] = e | ||
161 | |||
162 | def run_cmd(self, tempdir): | ||
163 | cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, | ||
164 | self.perf, self.command, tempdir, self.args) | ||
165 | ret = os.WEXITSTATUS(os.system(cmd)) | ||
166 | |||
167 | log.info(" running '%s' ret %d " % (cmd, ret)) | ||
168 | |||
169 | if ret != int(self.ret): | ||
170 | raise Unsup(self) | ||
171 | |||
172 | def compare(self, expect, result): | ||
173 | match = {} | ||
174 | |||
175 | log.info(" compare"); | ||
176 | |||
177 | # For each expected event find all matching | ||
178 | # events in result. Fail if there's not any. | ||
179 | for exp_name, exp_event in expect.items(): | ||
180 | exp_list = [] | ||
181 | log.debug(" matching [%s]" % exp_name) | ||
182 | for res_name, res_event in result.items(): | ||
183 | log.debug(" to [%s]" % res_name) | ||
184 | if (exp_event.equal(res_event)): | ||
185 | exp_list.append(res_name) | ||
186 | log.debug(" ->OK") | ||
187 | else: | ||
188 | log.debug(" ->FAIL"); | ||
189 | |||
190 | log.info(" match: [%s] matches %s" % (exp_name, str(exp_list))) | ||
191 | |||
192 | # we did not any matching event - fail | ||
193 | if (not exp_list): | ||
194 | raise Fail(self, 'match failure'); | ||
195 | |||
196 | match[exp_name] = exp_list | ||
197 | |||
198 | # For each defined group in the expected events | ||
199 | # check we match the same group in the result. | ||
200 | for exp_name, exp_event in expect.items(): | ||
201 | group = exp_event.group | ||
202 | |||
203 | if (group == ''): | ||
204 | continue | ||
205 | |||
206 | for res_name in match[exp_name]: | ||
207 | res_group = result[res_name].group | ||
208 | if res_group not in match[group]: | ||
209 | raise Fail(self, 'group failure') | ||
210 | |||
211 | log.info(" group: [%s] matches group leader %s" % | ||
212 | (exp_name, str(match[group]))) | ||
213 | |||
214 | log.info(" matched") | ||
215 | |||
216 | def resolve_groups(self, events): | ||
217 | for name, event in events.items(): | ||
218 | group_fd = event['group_fd']; | ||
219 | if group_fd == '-1': | ||
220 | continue; | ||
221 | |||
222 | for iname, ievent in events.items(): | ||
223 | if (ievent['fd'] == group_fd): | ||
224 | event.group = iname | ||
225 | log.debug('[%s] has group leader [%s]' % (name, iname)) | ||
226 | break; | ||
227 | |||
228 | def run(self): | ||
229 | tempdir = tempfile.mkdtemp(); | ||
230 | |||
231 | try: | ||
232 | # run the test script | ||
233 | self.run_cmd(tempdir); | ||
234 | |||
235 | # load events expectation for the test | ||
236 | log.info(" loading result events"); | ||
237 | for f in glob.glob(tempdir + '/event*'): | ||
238 | self.load_events(f, self.result); | ||
239 | |||
240 | # resolve group_fd to event names | ||
241 | self.resolve_groups(self.expect); | ||
242 | self.resolve_groups(self.result); | ||
243 | |||
244 | # do the expectation - results matching - both ways | ||
245 | self.compare(self.expect, self.result) | ||
246 | self.compare(self.result, self.expect) | ||
247 | |||
248 | finally: | ||
249 | # cleanup | ||
250 | shutil.rmtree(tempdir) | ||
251 | |||
252 | |||
253 | def run_tests(options): | ||
254 | for f in glob.glob(options.test_dir + '/' + options.test): | ||
255 | try: | ||
256 | Test(f, options).run() | ||
257 | except Unsup, obj: | ||
258 | log.warning("unsupp %s" % obj.getMsg()) | ||
259 | |||
260 | def setup_log(verbose): | ||
261 | global log | ||
262 | level = logging.CRITICAL | ||
263 | |||
264 | if verbose == 1: | ||
265 | level = logging.WARNING | ||
266 | if verbose == 2: | ||
267 | level = logging.INFO | ||
268 | if verbose >= 3: | ||
269 | level = logging.DEBUG | ||
270 | |||
271 | log = logging.getLogger('test') | ||
272 | log.setLevel(level) | ||
273 | ch = logging.StreamHandler() | ||
274 | ch.setLevel(level) | ||
275 | formatter = logging.Formatter('%(message)s') | ||
276 | ch.setFormatter(formatter) | ||
277 | log.addHandler(ch) | ||
278 | |||
279 | USAGE = '''%s [OPTIONS] | ||
280 | -d dir # tests dir | ||
281 | -p path # perf binary | ||
282 | -t test # single test | ||
283 | -v # verbose level | ||
284 | ''' % sys.argv[0] | ||
285 | |||
286 | def main(): | ||
287 | parser = optparse.OptionParser(usage=USAGE) | ||
288 | |||
289 | parser.add_option("-t", "--test", | ||
290 | action="store", type="string", dest="test") | ||
291 | parser.add_option("-d", "--test-dir", | ||
292 | action="store", type="string", dest="test_dir") | ||
293 | parser.add_option("-p", "--perf", | ||
294 | action="store", type="string", dest="perf") | ||
295 | parser.add_option("-v", "--verbose", | ||
296 | action="count", dest="verbose") | ||
297 | |||
298 | options, args = parser.parse_args() | ||
299 | if args: | ||
300 | parser.error('FAILED wrong arguments %s' % ' '.join(args)) | ||
301 | return -1 | ||
302 | |||
303 | setup_log(options.verbose) | ||
304 | |||
305 | if not options.test_dir: | ||
306 | print 'FAILED no -d option specified' | ||
307 | sys.exit(-1) | ||
308 | |||
309 | if not options.test: | ||
310 | options.test = 'test*' | ||
311 | |||
312 | try: | ||
313 | run_tests(options) | ||
314 | |||
315 | except Fail, obj: | ||
316 | print "FAILED %s" % obj.getMsg(); | ||
317 | sys.exit(-1) | ||
318 | |||
319 | sys.exit(0) | ||
320 | |||
321 | if __name__ == '__main__': | ||
322 | main() | ||
diff --git a/tools/perf/tests/attr/README b/tools/perf/tests/attr/README new file mode 100644 index 000000000000..d102957cd59a --- /dev/null +++ b/tools/perf/tests/attr/README | |||
@@ -0,0 +1,64 @@ | |||
1 | The struct perf_event_attr test (attr tests) support | ||
2 | ==================================================== | ||
3 | This testing support is embedded into perf directly and is governed | ||
4 | by the PERF_TEST_ATTR environment variable and hook inside the | ||
5 | sys_perf_event_open function. | ||
6 | |||
7 | The general idea is to store 'struct perf_event_attr' details for | ||
8 | each event created within single perf command. Each event details | ||
9 | are stored into separate text file. Once perf command is finished | ||
10 | these files are checked for values we expect for command. | ||
11 | |||
12 | The attr tests consist of following parts: | ||
13 | |||
14 | tests/attr.c | ||
15 | ------------ | ||
16 | This is the sys_perf_event_open hook implementation. The hook | ||
17 | is triggered when the PERF_TEST_ATTR environment variable is | ||
18 | defined. It must contain name of existing directory with access | ||
19 | and write permissions. | ||
20 | |||
21 | For each sys_perf_event_open call event details are stored in | ||
22 | separate file. Besides 'struct perf_event_attr' values we also | ||
23 | store 'fd' and 'group_fd' values to allow checking for groups. | ||
24 | |||
25 | tests/attr.py | ||
26 | ------------- | ||
27 | This is the python script that does all the hard work. It reads | ||
28 | the test definition, executes it and checks results. | ||
29 | |||
30 | tests/attr/ | ||
31 | ----------- | ||
32 | Directory containing all attr test definitions. | ||
33 | Following tests are defined (with perf commands): | ||
34 | |||
35 | perf record kill (test-record-basic) | ||
36 | perf record -b kill (test-record-branch-any) | ||
37 | perf record -j any kill (test-record-branch-filter-any) | ||
38 | perf record -j any_call kill (test-record-branch-filter-any_call) | ||
39 | perf record -j any_ret kill (test-record-branch-filter-any_ret) | ||
40 | perf record -j hv kill (test-record-branch-filter-hv) | ||
41 | perf record -j ind_call kill (test-record-branch-filter-ind_call) | ||
42 | perf record -j k kill (test-record-branch-filter-k) | ||
43 | perf record -j u kill (test-record-branch-filter-u) | ||
44 | perf record -c 123 kill (test-record-count) | ||
45 | perf record -d kill (test-record-data) | ||
46 | perf record -F 100 kill (test-record-freq) | ||
47 | perf record -g -- kill (test-record-graph-default) | ||
48 | perf record -g dwarf -- kill (test-record-graph-dwarf) | ||
49 | perf record -g fp kill (test-record-graph-fp) | ||
50 | perf record --group -e cycles,instructions kill (test-record-group) | ||
51 | perf record -e '{cycles,instructions}' kill (test-record-group1) | ||
52 | perf record -D kill (test-record-no-delay) | ||
53 | perf record -i kill (test-record-no-inherit) | ||
54 | perf record -n kill (test-record-no-samples) | ||
55 | perf record -c 100 -P kill (test-record-period) | ||
56 | perf record -R kill (test-record-raw) | ||
57 | perf stat -e cycles kill (test-stat-basic) | ||
58 | perf stat kill (test-stat-default) | ||
59 | perf stat -d kill (test-stat-detailed-1) | ||
60 | perf stat -dd kill (test-stat-detailed-2) | ||
61 | perf stat -ddd kill (test-stat-detailed-3) | ||
62 | perf stat --group -e cycles,instructions kill (test-stat-group) | ||
63 | perf stat -e '{cycles,instructions}' kill (test-stat-group1) | ||
64 | perf stat -i -e cycles kill (test-stat-no-inherit) | ||
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record new file mode 100644 index 000000000000..f1485d8e6a0b --- /dev/null +++ b/tools/perf/tests/attr/base-record | |||
@@ -0,0 +1,39 @@ | |||
1 | [event] | ||
2 | fd=1 | ||
3 | group_fd=-1 | ||
4 | flags=0 | ||
5 | type=0|1 | ||
6 | size=96 | ||
7 | config=0 | ||
8 | sample_period=4000 | ||
9 | sample_type=263 | ||
10 | read_format=7 | ||
11 | disabled=1 | ||
12 | inherit=1 | ||
13 | pinned=0 | ||
14 | exclusive=0 | ||
15 | exclude_user=0 | ||
16 | exclude_kernel=0 | ||
17 | exclude_hv=0 | ||
18 | exclude_idle=0 | ||
19 | mmap=1 | ||
20 | comm=1 | ||
21 | freq=1 | ||
22 | inherit_stat=0 | ||
23 | enable_on_exec=1 | ||
24 | task=0 | ||
25 | watermark=0 | ||
26 | precise_ip=0 | ||
27 | mmap_data=0 | ||
28 | sample_id_all=1 | ||
29 | exclude_host=0 | ||
30 | exclude_guest=1 | ||
31 | exclude_callchain_kernel=0 | ||
32 | exclude_callchain_user=0 | ||
33 | wakeup_events=0 | ||
34 | bp_type=0 | ||
35 | config1=0 | ||
36 | config2=0 | ||
37 | branch_sample_type=0 | ||
38 | sample_regs_user=0 | ||
39 | sample_stack_user=0 | ||
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat new file mode 100644 index 000000000000..4bd79a82784f --- /dev/null +++ b/tools/perf/tests/attr/base-stat | |||
@@ -0,0 +1,39 @@ | |||
1 | [event] | ||
2 | fd=1 | ||
3 | group_fd=-1 | ||
4 | flags=0 | ||
5 | type=0 | ||
6 | size=96 | ||
7 | config=0 | ||
8 | sample_period=0 | ||
9 | sample_type=0 | ||
10 | read_format=3 | ||
11 | disabled=1 | ||
12 | inherit=1 | ||
13 | pinned=0 | ||
14 | exclusive=0 | ||
15 | exclude_user=0 | ||
16 | exclude_kernel=0 | ||
17 | exclude_hv=0 | ||
18 | exclude_idle=0 | ||
19 | mmap=0 | ||
20 | comm=0 | ||
21 | freq=0 | ||
22 | inherit_stat=0 | ||
23 | enable_on_exec=1 | ||
24 | task=0 | ||
25 | watermark=0 | ||
26 | precise_ip=0 | ||
27 | mmap_data=0 | ||
28 | sample_id_all=0 | ||
29 | exclude_host=0 | ||
30 | exclude_guest=1 | ||
31 | exclude_callchain_kernel=0 | ||
32 | exclude_callchain_user=0 | ||
33 | wakeup_events=0 | ||
34 | bp_type=0 | ||
35 | config1=0 | ||
36 | config2=0 | ||
37 | branch_sample_type=0 | ||
38 | sample_regs_user=0 | ||
39 | sample_stack_user=0 | ||
diff --git a/tools/perf/tests/attr/test-record-basic b/tools/perf/tests/attr/test-record-basic new file mode 100644 index 000000000000..55c0428370ca --- /dev/null +++ b/tools/perf/tests/attr/test-record-basic | |||
@@ -0,0 +1,5 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any new file mode 100644 index 000000000000..1421960ed4e9 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-any | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -b kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any new file mode 100644 index 000000000000..915c4df0e0c2 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-any | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j any kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call new file mode 100644 index 000000000000..8708dbd4f373 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-any_call | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j any_call kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=16 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret new file mode 100644 index 000000000000..0d3607a6dcbe --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j any_ret kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=32 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv new file mode 100644 index 000000000000..f25526740cec --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-hv | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j hv kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call new file mode 100644 index 000000000000..e862dd179128 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j ind_call kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=64 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k new file mode 100644 index 000000000000..182971e898f5 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-k | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j k kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u new file mode 100644 index 000000000000..83449ef9e687 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-u | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j u kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-count b/tools/perf/tests/attr/test-record-count new file mode 100644 index 000000000000..2f841de56f6b --- /dev/null +++ b/tools/perf/tests/attr/test-record-count | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -c 123 kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=123 | ||
7 | sample_type=7 | ||
8 | freq=0 | ||
diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data new file mode 100644 index 000000000000..6627c3e7534a --- /dev/null +++ b/tools/perf/tests/attr/test-record-data | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -d kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=271 | ||
8 | mmap_data=1 | ||
diff --git a/tools/perf/tests/attr/test-record-freq b/tools/perf/tests/attr/test-record-freq new file mode 100644 index 000000000000..600d0f8f2583 --- /dev/null +++ b/tools/perf/tests/attr/test-record-freq | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -F 100 kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=100 | ||
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default new file mode 100644 index 000000000000..833d1849d767 --- /dev/null +++ b/tools/perf/tests/attr/test-record-graph-default | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -g -- kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=295 | ||
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf new file mode 100644 index 000000000000..e93e082f5208 --- /dev/null +++ b/tools/perf/tests/attr/test-record-graph-dwarf | |||
@@ -0,0 +1,10 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -g dwarf -- kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=12583 | ||
7 | exclude_callchain_user=1 | ||
8 | sample_stack_user=8192 | ||
9 | # TODO different for each arch, no support for that now | ||
10 | sample_regs_user=* | ||
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp new file mode 100644 index 000000000000..7cef3743f03f --- /dev/null +++ b/tools/perf/tests/attr/test-record-graph-fp | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -g fp kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=295 | ||
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group new file mode 100644 index 000000000000..b945f770dc9e --- /dev/null +++ b/tools/perf/tests/attr/test-record-group | |||
@@ -0,0 +1,17 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = --group -e cycles,instructions kill >/dev/null 2>&1 | ||
4 | |||
5 | [event-1:base-record] | ||
6 | fd=1 | ||
7 | group_fd=-1 | ||
8 | sample_type=327 | ||
9 | |||
10 | [event-2:base-record] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | config=1 | ||
14 | sample_type=327 | ||
15 | mmap=0 | ||
16 | comm=0 | ||
17 | enable_on_exec=0 | ||
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1 new file mode 100644 index 000000000000..39bf8609538c --- /dev/null +++ b/tools/perf/tests/attr/test-record-group1 | |||
@@ -0,0 +1,20 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1 | ||
4 | |||
5 | [event-1:base-record] | ||
6 | fd=1 | ||
7 | group_fd=-1 | ||
8 | sample_type=327 | ||
9 | |||
10 | [event-2:base-record] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | type=0 | ||
14 | config=1 | ||
15 | sample_type=327 | ||
16 | mmap=0 | ||
17 | comm=0 | ||
18 | # TODO this is disabled for --group option, enabled otherwise | ||
19 | # check why.. | ||
20 | enable_on_exec=1 | ||
diff --git a/tools/perf/tests/attr/test-record-no-delay b/tools/perf/tests/attr/test-record-no-delay new file mode 100644 index 000000000000..f253b78cdbf2 --- /dev/null +++ b/tools/perf/tests/attr/test-record-no-delay | |||
@@ -0,0 +1,9 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -D kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=263 | ||
8 | watermark=0 | ||
9 | wakeup_events=1 | ||
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit new file mode 100644 index 000000000000..9079a25cd643 --- /dev/null +++ b/tools/perf/tests/attr/test-record-no-inherit | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -i kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=259 | ||
7 | inherit=0 | ||
diff --git a/tools/perf/tests/attr/test-record-no-samples b/tools/perf/tests/attr/test-record-no-samples new file mode 100644 index 000000000000..d0141b2418b5 --- /dev/null +++ b/tools/perf/tests/attr/test-record-no-samples | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -n kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=0 | ||
diff --git a/tools/perf/tests/attr/test-record-period b/tools/perf/tests/attr/test-record-period new file mode 100644 index 000000000000..8abc5314fc52 --- /dev/null +++ b/tools/perf/tests/attr/test-record-period | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -c 100 -P kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=100 | ||
7 | freq=0 | ||
diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw new file mode 100644 index 000000000000..4a8ef25b5f49 --- /dev/null +++ b/tools/perf/tests/attr/test-record-raw | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -R kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=1415 | ||
diff --git a/tools/perf/tests/attr/test-stat-basic b/tools/perf/tests/attr/test-stat-basic new file mode 100644 index 000000000000..74e17881f2ba --- /dev/null +++ b/tools/perf/tests/attr/test-stat-basic | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -e cycles kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event:base-stat] | ||
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default new file mode 100644 index 000000000000..19270f54c96e --- /dev/null +++ b/tools/perf/tests/attr/test-stat-default | |||
@@ -0,0 +1,64 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
7 | [event1:base-stat] | ||
8 | fd=1 | ||
9 | type=1 | ||
10 | config=1 | ||
11 | |||
12 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
13 | [event2:base-stat] | ||
14 | fd=2 | ||
15 | type=1 | ||
16 | config=3 | ||
17 | |||
18 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
19 | [event3:base-stat] | ||
20 | fd=3 | ||
21 | type=1 | ||
22 | config=4 | ||
23 | |||
24 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
25 | [event4:base-stat] | ||
26 | fd=4 | ||
27 | type=1 | ||
28 | config=2 | ||
29 | |||
30 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
31 | [event5:base-stat] | ||
32 | fd=5 | ||
33 | type=0 | ||
34 | config=0 | ||
35 | |||
36 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
37 | [event6:base-stat] | ||
38 | fd=6 | ||
39 | type=0 | ||
40 | config=7 | ||
41 | |||
42 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
43 | [event7:base-stat] | ||
44 | fd=7 | ||
45 | type=0 | ||
46 | config=8 | ||
47 | |||
48 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
49 | [event8:base-stat] | ||
50 | fd=8 | ||
51 | type=0 | ||
52 | config=1 | ||
53 | |||
54 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
55 | [event9:base-stat] | ||
56 | fd=9 | ||
57 | type=0 | ||
58 | config=4 | ||
59 | |||
60 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
61 | [event10:base-stat] | ||
62 | fd=10 | ||
63 | type=0 | ||
64 | config=5 | ||
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1 new file mode 100644 index 000000000000..51426b87153b --- /dev/null +++ b/tools/perf/tests/attr/test-stat-detailed-1 | |||
@@ -0,0 +1,101 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -d kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | |||
7 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
8 | [event1:base-stat] | ||
9 | fd=1 | ||
10 | type=1 | ||
11 | config=1 | ||
12 | |||
13 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
14 | [event2:base-stat] | ||
15 | fd=2 | ||
16 | type=1 | ||
17 | config=3 | ||
18 | |||
19 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
20 | [event3:base-stat] | ||
21 | fd=3 | ||
22 | type=1 | ||
23 | config=4 | ||
24 | |||
25 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
26 | [event4:base-stat] | ||
27 | fd=4 | ||
28 | type=1 | ||
29 | config=2 | ||
30 | |||
31 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
32 | [event5:base-stat] | ||
33 | fd=5 | ||
34 | type=0 | ||
35 | config=0 | ||
36 | |||
37 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
38 | [event6:base-stat] | ||
39 | fd=6 | ||
40 | type=0 | ||
41 | config=7 | ||
42 | |||
43 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
44 | [event7:base-stat] | ||
45 | fd=7 | ||
46 | type=0 | ||
47 | config=8 | ||
48 | |||
49 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
50 | [event8:base-stat] | ||
51 | fd=8 | ||
52 | type=0 | ||
53 | config=1 | ||
54 | |||
55 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
56 | [event9:base-stat] | ||
57 | fd=9 | ||
58 | type=0 | ||
59 | config=4 | ||
60 | |||
61 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
62 | [event10:base-stat] | ||
63 | fd=10 | ||
64 | type=0 | ||
65 | config=5 | ||
66 | |||
67 | # PERF_TYPE_HW_CACHE / | ||
68 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
69 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
70 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
71 | [event11:base-stat] | ||
72 | fd=11 | ||
73 | type=3 | ||
74 | config=0 | ||
75 | |||
76 | # PERF_TYPE_HW_CACHE / | ||
77 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
78 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
79 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
80 | [event12:base-stat] | ||
81 | fd=12 | ||
82 | type=3 | ||
83 | config=65536 | ||
84 | |||
85 | # PERF_TYPE_HW_CACHE / | ||
86 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
87 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
88 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
89 | [event13:base-stat] | ||
90 | fd=13 | ||
91 | type=3 | ||
92 | config=2 | ||
93 | |||
94 | # PERF_TYPE_HW_CACHE, | ||
95 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
96 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
97 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
98 | [event14:base-stat] | ||
99 | fd=14 | ||
100 | type=3 | ||
101 | config=65538 | ||
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2 new file mode 100644 index 000000000000..8de5acc31c27 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-detailed-2 | |||
@@ -0,0 +1,155 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -dd kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | |||
7 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
8 | [event1:base-stat] | ||
9 | fd=1 | ||
10 | type=1 | ||
11 | config=1 | ||
12 | |||
13 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
14 | [event2:base-stat] | ||
15 | fd=2 | ||
16 | type=1 | ||
17 | config=3 | ||
18 | |||
19 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
20 | [event3:base-stat] | ||
21 | fd=3 | ||
22 | type=1 | ||
23 | config=4 | ||
24 | |||
25 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
26 | [event4:base-stat] | ||
27 | fd=4 | ||
28 | type=1 | ||
29 | config=2 | ||
30 | |||
31 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
32 | [event5:base-stat] | ||
33 | fd=5 | ||
34 | type=0 | ||
35 | config=0 | ||
36 | |||
37 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
38 | [event6:base-stat] | ||
39 | fd=6 | ||
40 | type=0 | ||
41 | config=7 | ||
42 | |||
43 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
44 | [event7:base-stat] | ||
45 | fd=7 | ||
46 | type=0 | ||
47 | config=8 | ||
48 | |||
49 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
50 | [event8:base-stat] | ||
51 | fd=8 | ||
52 | type=0 | ||
53 | config=1 | ||
54 | |||
55 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
56 | [event9:base-stat] | ||
57 | fd=9 | ||
58 | type=0 | ||
59 | config=4 | ||
60 | |||
61 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
62 | [event10:base-stat] | ||
63 | fd=10 | ||
64 | type=0 | ||
65 | config=5 | ||
66 | |||
67 | # PERF_TYPE_HW_CACHE / | ||
68 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
69 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
70 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
71 | [event11:base-stat] | ||
72 | fd=11 | ||
73 | type=3 | ||
74 | config=0 | ||
75 | |||
76 | # PERF_TYPE_HW_CACHE / | ||
77 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
78 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
79 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
80 | [event12:base-stat] | ||
81 | fd=12 | ||
82 | type=3 | ||
83 | config=65536 | ||
84 | |||
85 | # PERF_TYPE_HW_CACHE / | ||
86 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
87 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
88 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
89 | [event13:base-stat] | ||
90 | fd=13 | ||
91 | type=3 | ||
92 | config=2 | ||
93 | |||
94 | # PERF_TYPE_HW_CACHE, | ||
95 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
96 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
97 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
98 | [event14:base-stat] | ||
99 | fd=14 | ||
100 | type=3 | ||
101 | config=65538 | ||
102 | |||
103 | # PERF_TYPE_HW_CACHE, | ||
104 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
105 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
106 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
107 | [event15:base-stat] | ||
108 | fd=15 | ||
109 | type=3 | ||
110 | config=1 | ||
111 | |||
112 | # PERF_TYPE_HW_CACHE, | ||
113 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
114 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
115 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
116 | [event16:base-stat] | ||
117 | fd=16 | ||
118 | type=3 | ||
119 | config=65537 | ||
120 | |||
121 | # PERF_TYPE_HW_CACHE, | ||
122 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
123 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
124 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
125 | [event17:base-stat] | ||
126 | fd=17 | ||
127 | type=3 | ||
128 | config=3 | ||
129 | |||
130 | # PERF_TYPE_HW_CACHE, | ||
131 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
132 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
133 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
134 | [event18:base-stat] | ||
135 | fd=18 | ||
136 | type=3 | ||
137 | config=65539 | ||
138 | |||
139 | # PERF_TYPE_HW_CACHE, | ||
140 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
141 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
142 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
143 | [event19:base-stat] | ||
144 | fd=19 | ||
145 | type=3 | ||
146 | config=4 | ||
147 | |||
148 | # PERF_TYPE_HW_CACHE, | ||
149 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
150 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
151 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
152 | [event20:base-stat] | ||
153 | fd=20 | ||
154 | type=3 | ||
155 | config=65540 | ||
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3 new file mode 100644 index 000000000000..0a1f45bf7d79 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-detailed-3 | |||
@@ -0,0 +1,173 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -ddd kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | |||
7 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
8 | [event1:base-stat] | ||
9 | fd=1 | ||
10 | type=1 | ||
11 | config=1 | ||
12 | |||
13 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
14 | [event2:base-stat] | ||
15 | fd=2 | ||
16 | type=1 | ||
17 | config=3 | ||
18 | |||
19 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
20 | [event3:base-stat] | ||
21 | fd=3 | ||
22 | type=1 | ||
23 | config=4 | ||
24 | |||
25 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
26 | [event4:base-stat] | ||
27 | fd=4 | ||
28 | type=1 | ||
29 | config=2 | ||
30 | |||
31 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
32 | [event5:base-stat] | ||
33 | fd=5 | ||
34 | type=0 | ||
35 | config=0 | ||
36 | |||
37 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
38 | [event6:base-stat] | ||
39 | fd=6 | ||
40 | type=0 | ||
41 | config=7 | ||
42 | |||
43 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
44 | [event7:base-stat] | ||
45 | fd=7 | ||
46 | type=0 | ||
47 | config=8 | ||
48 | |||
49 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
50 | [event8:base-stat] | ||
51 | fd=8 | ||
52 | type=0 | ||
53 | config=1 | ||
54 | |||
55 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
56 | [event9:base-stat] | ||
57 | fd=9 | ||
58 | type=0 | ||
59 | config=4 | ||
60 | |||
61 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
62 | [event10:base-stat] | ||
63 | fd=10 | ||
64 | type=0 | ||
65 | config=5 | ||
66 | |||
67 | # PERF_TYPE_HW_CACHE / | ||
68 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
69 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
70 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
71 | [event11:base-stat] | ||
72 | fd=11 | ||
73 | type=3 | ||
74 | config=0 | ||
75 | |||
76 | # PERF_TYPE_HW_CACHE / | ||
77 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
78 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
79 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
80 | [event12:base-stat] | ||
81 | fd=12 | ||
82 | type=3 | ||
83 | config=65536 | ||
84 | |||
85 | # PERF_TYPE_HW_CACHE / | ||
86 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
87 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
88 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
89 | [event13:base-stat] | ||
90 | fd=13 | ||
91 | type=3 | ||
92 | config=2 | ||
93 | |||
94 | # PERF_TYPE_HW_CACHE, | ||
95 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
96 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
97 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
98 | [event14:base-stat] | ||
99 | fd=14 | ||
100 | type=3 | ||
101 | config=65538 | ||
102 | |||
103 | # PERF_TYPE_HW_CACHE, | ||
104 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
105 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
106 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
107 | [event15:base-stat] | ||
108 | fd=15 | ||
109 | type=3 | ||
110 | config=1 | ||
111 | |||
112 | # PERF_TYPE_HW_CACHE, | ||
113 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
114 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
115 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
116 | [event16:base-stat] | ||
117 | fd=16 | ||
118 | type=3 | ||
119 | config=65537 | ||
120 | |||
121 | # PERF_TYPE_HW_CACHE, | ||
122 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
123 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
124 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
125 | [event17:base-stat] | ||
126 | fd=17 | ||
127 | type=3 | ||
128 | config=3 | ||
129 | |||
130 | # PERF_TYPE_HW_CACHE, | ||
131 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
132 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
133 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
134 | [event18:base-stat] | ||
135 | fd=18 | ||
136 | type=3 | ||
137 | config=65539 | ||
138 | |||
139 | # PERF_TYPE_HW_CACHE, | ||
140 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
141 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
142 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
143 | [event19:base-stat] | ||
144 | fd=19 | ||
145 | type=3 | ||
146 | config=4 | ||
147 | |||
148 | # PERF_TYPE_HW_CACHE, | ||
149 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
150 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
151 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
152 | [event20:base-stat] | ||
153 | fd=20 | ||
154 | type=3 | ||
155 | config=65540 | ||
156 | |||
157 | # PERF_TYPE_HW_CACHE, | ||
158 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
159 | # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | | ||
160 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
161 | [event21:base-stat] | ||
162 | fd=21 | ||
163 | type=3 | ||
164 | config=512 | ||
165 | |||
166 | # PERF_TYPE_HW_CACHE, | ||
167 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
168 | # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | | ||
169 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
170 | [event22:base-stat] | ||
171 | fd=22 | ||
172 | type=3 | ||
173 | config=66048 | ||
diff --git a/tools/perf/tests/attr/test-stat-group b/tools/perf/tests/attr/test-stat-group new file mode 100644 index 000000000000..fdc1596a8862 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-group | |||
@@ -0,0 +1,15 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = --group -e cycles,instructions kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event-1:base-stat] | ||
7 | fd=1 | ||
8 | group_fd=-1 | ||
9 | |||
10 | [event-2:base-stat] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | config=1 | ||
14 | disabled=0 | ||
15 | enable_on_exec=0 | ||
diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1 new file mode 100644 index 000000000000..5ae2718de864 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-group1 | |||
@@ -0,0 +1,17 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -e '{cycles,instructions}' kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event-1:base-stat] | ||
7 | fd=1 | ||
8 | group_fd=-1 | ||
9 | |||
10 | [event-2:base-stat] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | config=1 | ||
14 | # TODO both disabled and enable_on_exec are disabled for --group option, | ||
15 | # enabled otherwise, check why.. | ||
16 | disabled=1 | ||
17 | enable_on_exec=1 | ||
diff --git a/tools/perf/tests/attr/test-stat-no-inherit b/tools/perf/tests/attr/test-stat-no-inherit new file mode 100644 index 000000000000..d54b2a1e3e28 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-no-inherit | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -i -e cycles kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event:base-stat] | ||
7 | inherit=0 | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c new file mode 100644 index 000000000000..5d4354e24457 --- /dev/null +++ b/tools/perf/tests/builtin-test.c | |||
@@ -0,0 +1,1550 @@ | |||
1 | /* | ||
2 | * builtin-test.c | ||
3 | * | ||
4 | * Builtin regression testing command: ever growing number of sanity tests | ||
5 | */ | ||
6 | #include "builtin.h" | ||
7 | |||
8 | #include "util/cache.h" | ||
9 | #include "util/color.h" | ||
10 | #include "util/debug.h" | ||
11 | #include "util/debugfs.h" | ||
12 | #include "util/evlist.h" | ||
13 | #include "util/machine.h" | ||
14 | #include "util/parse-options.h" | ||
15 | #include "util/parse-events.h" | ||
16 | #include "util/symbol.h" | ||
17 | #include "util/thread_map.h" | ||
18 | #include "util/pmu.h" | ||
19 | #include "event-parse.h" | ||
20 | #include "../../include/linux/hw_breakpoint.h" | ||
21 | |||
22 | #include <sys/mman.h> | ||
23 | |||
24 | static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused, | ||
25 | struct symbol *sym) | ||
26 | { | ||
27 | bool *visited = symbol__priv(sym); | ||
28 | *visited = true; | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static int test__vmlinux_matches_kallsyms(void) | ||
33 | { | ||
34 | int err = -1; | ||
35 | struct rb_node *nd; | ||
36 | struct symbol *sym; | ||
37 | struct map *kallsyms_map, *vmlinux_map; | ||
38 | struct machine kallsyms, vmlinux; | ||
39 | enum map_type type = MAP__FUNCTION; | ||
40 | struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; | ||
41 | |||
42 | /* | ||
43 | * Step 1: | ||
44 | * | ||
45 | * Init the machines that will hold kernel, modules obtained from | ||
46 | * both vmlinux + .ko files and from /proc/kallsyms split by modules. | ||
47 | */ | ||
48 | machine__init(&kallsyms, "", HOST_KERNEL_ID); | ||
49 | machine__init(&vmlinux, "", HOST_KERNEL_ID); | ||
50 | |||
51 | /* | ||
52 | * Step 2: | ||
53 | * | ||
54 | * Create the kernel maps for kallsyms and the DSO where we will then | ||
55 | * load /proc/kallsyms. Also create the modules maps from /proc/modules | ||
56 | * and find the .ko files that match them in /lib/modules/`uname -r`/. | ||
57 | */ | ||
58 | if (machine__create_kernel_maps(&kallsyms) < 0) { | ||
59 | pr_debug("machine__create_kernel_maps "); | ||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Step 3: | ||
65 | * | ||
66 | * Load and split /proc/kallsyms into multiple maps, one per module. | ||
67 | */ | ||
68 | if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { | ||
69 | pr_debug("dso__load_kallsyms "); | ||
70 | goto out; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Step 4: | ||
75 | * | ||
76 | * kallsyms will be internally on demand sorted by name so that we can | ||
77 | * find the reference relocation * symbol, i.e. the symbol we will use | ||
78 | * to see if the running kernel was relocated by checking if it has the | ||
79 | * same value in the vmlinux file we load. | ||
80 | */ | ||
81 | kallsyms_map = machine__kernel_map(&kallsyms, type); | ||
82 | |||
83 | sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); | ||
84 | if (sym == NULL) { | ||
85 | pr_debug("dso__find_symbol_by_name "); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | ref_reloc_sym.addr = sym->start; | ||
90 | |||
91 | /* | ||
92 | * Step 5: | ||
93 | * | ||
94 | * Now repeat step 2, this time for the vmlinux file we'll auto-locate. | ||
95 | */ | ||
96 | if (machine__create_kernel_maps(&vmlinux) < 0) { | ||
97 | pr_debug("machine__create_kernel_maps "); | ||
98 | goto out; | ||
99 | } | ||
100 | |||
101 | vmlinux_map = machine__kernel_map(&vmlinux, type); | ||
102 | map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; | ||
103 | |||
104 | /* | ||
105 | * Step 6: | ||
106 | * | ||
107 | * Locate a vmlinux file in the vmlinux path that has a buildid that | ||
108 | * matches the one of the running kernel. | ||
109 | * | ||
110 | * While doing that look if we find the ref reloc symbol, if we find it | ||
111 | * we'll have its ref_reloc_symbol.unrelocated_addr and then | ||
112 | * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines | ||
113 | * to fixup the symbols. | ||
114 | */ | ||
115 | if (machine__load_vmlinux_path(&vmlinux, type, | ||
116 | vmlinux_matches_kallsyms_filter) <= 0) { | ||
117 | pr_debug("machine__load_vmlinux_path "); | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | err = 0; | ||
122 | /* | ||
123 | * Step 7: | ||
124 | * | ||
125 | * Now look at the symbols in the vmlinux DSO and check if we find all of them | ||
126 | * in the kallsyms dso. For the ones that are in both, check its names and | ||
127 | * end addresses too. | ||
128 | */ | ||
129 | for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { | ||
130 | struct symbol *pair, *first_pair; | ||
131 | bool backwards = true; | ||
132 | |||
133 | sym = rb_entry(nd, struct symbol, rb_node); | ||
134 | |||
135 | if (sym->start == sym->end) | ||
136 | continue; | ||
137 | |||
138 | first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); | ||
139 | pair = first_pair; | ||
140 | |||
141 | if (pair && pair->start == sym->start) { | ||
142 | next_pair: | ||
143 | if (strcmp(sym->name, pair->name) == 0) { | ||
144 | /* | ||
145 | * kallsyms don't have the symbol end, so we | ||
146 | * set that by using the next symbol start - 1, | ||
147 | * in some cases we get this up to a page | ||
148 | * wrong, trace_kmalloc when I was developing | ||
149 | * this code was one such example, 2106 bytes | ||
150 | * off the real size. More than that and we | ||
151 | * _really_ have a problem. | ||
152 | */ | ||
153 | s64 skew = sym->end - pair->end; | ||
154 | if (llabs(skew) < page_size) | ||
155 | continue; | ||
156 | |||
157 | pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", | ||
158 | sym->start, sym->name, sym->end, pair->end); | ||
159 | } else { | ||
160 | struct rb_node *nnd; | ||
161 | detour: | ||
162 | nnd = backwards ? rb_prev(&pair->rb_node) : | ||
163 | rb_next(&pair->rb_node); | ||
164 | if (nnd) { | ||
165 | struct symbol *next = rb_entry(nnd, struct symbol, rb_node); | ||
166 | |||
167 | if (next->start == sym->start) { | ||
168 | pair = next; | ||
169 | goto next_pair; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | if (backwards) { | ||
174 | backwards = false; | ||
175 | pair = first_pair; | ||
176 | goto detour; | ||
177 | } | ||
178 | |||
179 | pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", | ||
180 | sym->start, sym->name, pair->name); | ||
181 | } | ||
182 | } else | ||
183 | pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name); | ||
184 | |||
185 | err = -1; | ||
186 | } | ||
187 | |||
188 | if (!verbose) | ||
189 | goto out; | ||
190 | |||
191 | pr_info("Maps only in vmlinux:\n"); | ||
192 | |||
193 | for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { | ||
194 | struct map *pos = rb_entry(nd, struct map, rb_node), *pair; | ||
195 | /* | ||
196 | * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while | ||
197 | * the kernel will have the path for the vmlinux file being used, | ||
198 | * so use the short name, less descriptive but the same ("[kernel]" in | ||
199 | * both cases. | ||
200 | */ | ||
201 | pair = map_groups__find_by_name(&kallsyms.kmaps, type, | ||
202 | (pos->dso->kernel ? | ||
203 | pos->dso->short_name : | ||
204 | pos->dso->name)); | ||
205 | if (pair) | ||
206 | pair->priv = 1; | ||
207 | else | ||
208 | map__fprintf(pos, stderr); | ||
209 | } | ||
210 | |||
211 | pr_info("Maps in vmlinux with a different name in kallsyms:\n"); | ||
212 | |||
213 | for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { | ||
214 | struct map *pos = rb_entry(nd, struct map, rb_node), *pair; | ||
215 | |||
216 | pair = map_groups__find(&kallsyms.kmaps, type, pos->start); | ||
217 | if (pair == NULL || pair->priv) | ||
218 | continue; | ||
219 | |||
220 | if (pair->start == pos->start) { | ||
221 | pair->priv = 1; | ||
222 | pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", | ||
223 | pos->start, pos->end, pos->pgoff, pos->dso->name); | ||
224 | if (pos->pgoff != pair->pgoff || pos->end != pair->end) | ||
225 | pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "", | ||
226 | pair->start, pair->end, pair->pgoff); | ||
227 | pr_info(" %s\n", pair->dso->name); | ||
228 | pair->priv = 1; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | pr_info("Maps only in kallsyms:\n"); | ||
233 | |||
234 | for (nd = rb_first(&kallsyms.kmaps.maps[type]); | ||
235 | nd; nd = rb_next(nd)) { | ||
236 | struct map *pos = rb_entry(nd, struct map, rb_node); | ||
237 | |||
238 | if (!pos->priv) | ||
239 | map__fprintf(pos, stderr); | ||
240 | } | ||
241 | out: | ||
242 | return err; | ||
243 | } | ||
244 | |||
245 | #include "util/cpumap.h" | ||
246 | #include "util/evsel.h" | ||
247 | #include <sys/types.h> | ||
248 | |||
249 | static int trace_event__id(const char *evname) | ||
250 | { | ||
251 | char *filename; | ||
252 | int err = -1, fd; | ||
253 | |||
254 | if (asprintf(&filename, | ||
255 | "%s/syscalls/%s/id", | ||
256 | tracing_events_path, evname) < 0) | ||
257 | return -1; | ||
258 | |||
259 | fd = open(filename, O_RDONLY); | ||
260 | if (fd >= 0) { | ||
261 | char id[16]; | ||
262 | if (read(fd, id, sizeof(id)) > 0) | ||
263 | err = atoi(id); | ||
264 | close(fd); | ||
265 | } | ||
266 | |||
267 | free(filename); | ||
268 | return err; | ||
269 | } | ||
270 | |||
271 | static int test__open_syscall_event(void) | ||
272 | { | ||
273 | int err = -1, fd; | ||
274 | struct thread_map *threads; | ||
275 | struct perf_evsel *evsel; | ||
276 | struct perf_event_attr attr; | ||
277 | unsigned int nr_open_calls = 111, i; | ||
278 | int id = trace_event__id("sys_enter_open"); | ||
279 | |||
280 | if (id < 0) { | ||
281 | pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); | ||
282 | return -1; | ||
283 | } | ||
284 | |||
285 | threads = thread_map__new(-1, getpid(), UINT_MAX); | ||
286 | if (threads == NULL) { | ||
287 | pr_debug("thread_map__new\n"); | ||
288 | return -1; | ||
289 | } | ||
290 | |||
291 | memset(&attr, 0, sizeof(attr)); | ||
292 | attr.type = PERF_TYPE_TRACEPOINT; | ||
293 | attr.config = id; | ||
294 | evsel = perf_evsel__new(&attr, 0); | ||
295 | if (evsel == NULL) { | ||
296 | pr_debug("perf_evsel__new\n"); | ||
297 | goto out_thread_map_delete; | ||
298 | } | ||
299 | |||
300 | if (perf_evsel__open_per_thread(evsel, threads) < 0) { | ||
301 | pr_debug("failed to open counter: %s, " | ||
302 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | ||
303 | strerror(errno)); | ||
304 | goto out_evsel_delete; | ||
305 | } | ||
306 | |||
307 | for (i = 0; i < nr_open_calls; ++i) { | ||
308 | fd = open("/etc/passwd", O_RDONLY); | ||
309 | close(fd); | ||
310 | } | ||
311 | |||
312 | if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { | ||
313 | pr_debug("perf_evsel__read_on_cpu\n"); | ||
314 | goto out_close_fd; | ||
315 | } | ||
316 | |||
317 | if (evsel->counts->cpu[0].val != nr_open_calls) { | ||
318 | pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", | ||
319 | nr_open_calls, evsel->counts->cpu[0].val); | ||
320 | goto out_close_fd; | ||
321 | } | ||
322 | |||
323 | err = 0; | ||
324 | out_close_fd: | ||
325 | perf_evsel__close_fd(evsel, 1, threads->nr); | ||
326 | out_evsel_delete: | ||
327 | perf_evsel__delete(evsel); | ||
328 | out_thread_map_delete: | ||
329 | thread_map__delete(threads); | ||
330 | return err; | ||
331 | } | ||
332 | |||
333 | #include <sched.h> | ||
334 | |||
335 | static int test__open_syscall_event_on_all_cpus(void) | ||
336 | { | ||
337 | int err = -1, fd, cpu; | ||
338 | struct thread_map *threads; | ||
339 | struct cpu_map *cpus; | ||
340 | struct perf_evsel *evsel; | ||
341 | struct perf_event_attr attr; | ||
342 | unsigned int nr_open_calls = 111, i; | ||
343 | cpu_set_t cpu_set; | ||
344 | int id = trace_event__id("sys_enter_open"); | ||
345 | |||
346 | if (id < 0) { | ||
347 | pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); | ||
348 | return -1; | ||
349 | } | ||
350 | |||
351 | threads = thread_map__new(-1, getpid(), UINT_MAX); | ||
352 | if (threads == NULL) { | ||
353 | pr_debug("thread_map__new\n"); | ||
354 | return -1; | ||
355 | } | ||
356 | |||
357 | cpus = cpu_map__new(NULL); | ||
358 | if (cpus == NULL) { | ||
359 | pr_debug("cpu_map__new\n"); | ||
360 | goto out_thread_map_delete; | ||
361 | } | ||
362 | |||
363 | |||
364 | CPU_ZERO(&cpu_set); | ||
365 | |||
366 | memset(&attr, 0, sizeof(attr)); | ||
367 | attr.type = PERF_TYPE_TRACEPOINT; | ||
368 | attr.config = id; | ||
369 | evsel = perf_evsel__new(&attr, 0); | ||
370 | if (evsel == NULL) { | ||
371 | pr_debug("perf_evsel__new\n"); | ||
372 | goto out_thread_map_delete; | ||
373 | } | ||
374 | |||
375 | if (perf_evsel__open(evsel, cpus, threads) < 0) { | ||
376 | pr_debug("failed to open counter: %s, " | ||
377 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | ||
378 | strerror(errno)); | ||
379 | goto out_evsel_delete; | ||
380 | } | ||
381 | |||
382 | for (cpu = 0; cpu < cpus->nr; ++cpu) { | ||
383 | unsigned int ncalls = nr_open_calls + cpu; | ||
384 | /* | ||
385 | * XXX eventually lift this restriction in a way that | ||
386 | * keeps perf building on older glibc installations | ||
387 | * without CPU_ALLOC. 1024 cpus in 2010 still seems | ||
388 | * a reasonable upper limit tho :-) | ||
389 | */ | ||
390 | if (cpus->map[cpu] >= CPU_SETSIZE) { | ||
391 | pr_debug("Ignoring CPU %d\n", cpus->map[cpu]); | ||
392 | continue; | ||
393 | } | ||
394 | |||
395 | CPU_SET(cpus->map[cpu], &cpu_set); | ||
396 | if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { | ||
397 | pr_debug("sched_setaffinity() failed on CPU %d: %s ", | ||
398 | cpus->map[cpu], | ||
399 | strerror(errno)); | ||
400 | goto out_close_fd; | ||
401 | } | ||
402 | for (i = 0; i < ncalls; ++i) { | ||
403 | fd = open("/etc/passwd", O_RDONLY); | ||
404 | close(fd); | ||
405 | } | ||
406 | CPU_CLR(cpus->map[cpu], &cpu_set); | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * Here we need to explicitely preallocate the counts, as if | ||
411 | * we use the auto allocation it will allocate just for 1 cpu, | ||
412 | * as we start by cpu 0. | ||
413 | */ | ||
414 | if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) { | ||
415 | pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr); | ||
416 | goto out_close_fd; | ||
417 | } | ||
418 | |||
419 | err = 0; | ||
420 | |||
421 | for (cpu = 0; cpu < cpus->nr; ++cpu) { | ||
422 | unsigned int expected; | ||
423 | |||
424 | if (cpus->map[cpu] >= CPU_SETSIZE) | ||
425 | continue; | ||
426 | |||
427 | if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { | ||
428 | pr_debug("perf_evsel__read_on_cpu\n"); | ||
429 | err = -1; | ||
430 | break; | ||
431 | } | ||
432 | |||
433 | expected = nr_open_calls + cpu; | ||
434 | if (evsel->counts->cpu[cpu].val != expected) { | ||
435 | pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", | ||
436 | expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); | ||
437 | err = -1; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | out_close_fd: | ||
442 | perf_evsel__close_fd(evsel, 1, threads->nr); | ||
443 | out_evsel_delete: | ||
444 | perf_evsel__delete(evsel); | ||
445 | out_thread_map_delete: | ||
446 | thread_map__delete(threads); | ||
447 | return err; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * This test will generate random numbers of calls to some getpid syscalls, | ||
452 | * then establish an mmap for a group of events that are created to monitor | ||
453 | * the syscalls. | ||
454 | * | ||
455 | * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated | ||
456 | * sample.id field to map back to its respective perf_evsel instance. | ||
457 | * | ||
458 | * Then it checks if the number of syscalls reported as perf events by | ||
459 | * the kernel corresponds to the number of syscalls made. | ||
460 | */ | ||
461 | static int test__basic_mmap(void) | ||
462 | { | ||
463 | int err = -1; | ||
464 | union perf_event *event; | ||
465 | struct thread_map *threads; | ||
466 | struct cpu_map *cpus; | ||
467 | struct perf_evlist *evlist; | ||
468 | struct perf_event_attr attr = { | ||
469 | .type = PERF_TYPE_TRACEPOINT, | ||
470 | .read_format = PERF_FORMAT_ID, | ||
471 | .sample_type = PERF_SAMPLE_ID, | ||
472 | .watermark = 0, | ||
473 | }; | ||
474 | cpu_set_t cpu_set; | ||
475 | const char *syscall_names[] = { "getsid", "getppid", "getpgrp", | ||
476 | "getpgid", }; | ||
477 | pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, | ||
478 | (void*)getpgid }; | ||
479 | #define nsyscalls ARRAY_SIZE(syscall_names) | ||
480 | int ids[nsyscalls]; | ||
481 | unsigned int nr_events[nsyscalls], | ||
482 | expected_nr_events[nsyscalls], i, j; | ||
483 | struct perf_evsel *evsels[nsyscalls], *evsel; | ||
484 | |||
485 | for (i = 0; i < nsyscalls; ++i) { | ||
486 | char name[64]; | ||
487 | |||
488 | snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); | ||
489 | ids[i] = trace_event__id(name); | ||
490 | if (ids[i] < 0) { | ||
491 | pr_debug("Is debugfs mounted on /sys/kernel/debug?\n"); | ||
492 | return -1; | ||
493 | } | ||
494 | nr_events[i] = 0; | ||
495 | expected_nr_events[i] = random() % 257; | ||
496 | } | ||
497 | |||
498 | threads = thread_map__new(-1, getpid(), UINT_MAX); | ||
499 | if (threads == NULL) { | ||
500 | pr_debug("thread_map__new\n"); | ||
501 | return -1; | ||
502 | } | ||
503 | |||
504 | cpus = cpu_map__new(NULL); | ||
505 | if (cpus == NULL) { | ||
506 | pr_debug("cpu_map__new\n"); | ||
507 | goto out_free_threads; | ||
508 | } | ||
509 | |||
510 | CPU_ZERO(&cpu_set); | ||
511 | CPU_SET(cpus->map[0], &cpu_set); | ||
512 | sched_setaffinity(0, sizeof(cpu_set), &cpu_set); | ||
513 | if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { | ||
514 | pr_debug("sched_setaffinity() failed on CPU %d: %s ", | ||
515 | cpus->map[0], strerror(errno)); | ||
516 | goto out_free_cpus; | ||
517 | } | ||
518 | |||
519 | evlist = perf_evlist__new(cpus, threads); | ||
520 | if (evlist == NULL) { | ||
521 | pr_debug("perf_evlist__new\n"); | ||
522 | goto out_free_cpus; | ||
523 | } | ||
524 | |||
525 | /* anonymous union fields, can't be initialized above */ | ||
526 | attr.wakeup_events = 1; | ||
527 | attr.sample_period = 1; | ||
528 | |||
529 | for (i = 0; i < nsyscalls; ++i) { | ||
530 | attr.config = ids[i]; | ||
531 | evsels[i] = perf_evsel__new(&attr, i); | ||
532 | if (evsels[i] == NULL) { | ||
533 | pr_debug("perf_evsel__new\n"); | ||
534 | goto out_free_evlist; | ||
535 | } | ||
536 | |||
537 | perf_evlist__add(evlist, evsels[i]); | ||
538 | |||
539 | if (perf_evsel__open(evsels[i], cpus, threads) < 0) { | ||
540 | pr_debug("failed to open counter: %s, " | ||
541 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | ||
542 | strerror(errno)); | ||
543 | goto out_close_fd; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | if (perf_evlist__mmap(evlist, 128, true) < 0) { | ||
548 | pr_debug("failed to mmap events: %d (%s)\n", errno, | ||
549 | strerror(errno)); | ||
550 | goto out_close_fd; | ||
551 | } | ||
552 | |||
553 | for (i = 0; i < nsyscalls; ++i) | ||
554 | for (j = 0; j < expected_nr_events[i]; ++j) { | ||
555 | int foo = syscalls[i](); | ||
556 | ++foo; | ||
557 | } | ||
558 | |||
559 | while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { | ||
560 | struct perf_sample sample; | ||
561 | |||
562 | if (event->header.type != PERF_RECORD_SAMPLE) { | ||
563 | pr_debug("unexpected %s event\n", | ||
564 | perf_event__name(event->header.type)); | ||
565 | goto out_munmap; | ||
566 | } | ||
567 | |||
568 | err = perf_evlist__parse_sample(evlist, event, &sample); | ||
569 | if (err) { | ||
570 | pr_err("Can't parse sample, err = %d\n", err); | ||
571 | goto out_munmap; | ||
572 | } | ||
573 | |||
574 | evsel = perf_evlist__id2evsel(evlist, sample.id); | ||
575 | if (evsel == NULL) { | ||
576 | pr_debug("event with id %" PRIu64 | ||
577 | " doesn't map to an evsel\n", sample.id); | ||
578 | goto out_munmap; | ||
579 | } | ||
580 | nr_events[evsel->idx]++; | ||
581 | } | ||
582 | |||
583 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
584 | if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { | ||
585 | pr_debug("expected %d %s events, got %d\n", | ||
586 | expected_nr_events[evsel->idx], | ||
587 | perf_evsel__name(evsel), nr_events[evsel->idx]); | ||
588 | goto out_munmap; | ||
589 | } | ||
590 | } | ||
591 | |||
592 | err = 0; | ||
593 | out_munmap: | ||
594 | perf_evlist__munmap(evlist); | ||
595 | out_close_fd: | ||
596 | for (i = 0; i < nsyscalls; ++i) | ||
597 | perf_evsel__close_fd(evsels[i], 1, threads->nr); | ||
598 | out_free_evlist: | ||
599 | perf_evlist__delete(evlist); | ||
600 | out_free_cpus: | ||
601 | cpu_map__delete(cpus); | ||
602 | out_free_threads: | ||
603 | thread_map__delete(threads); | ||
604 | return err; | ||
605 | #undef nsyscalls | ||
606 | } | ||
607 | |||
608 | static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) | ||
609 | { | ||
610 | int i, cpu = -1, nrcpus = 1024; | ||
611 | realloc: | ||
612 | CPU_ZERO(maskp); | ||
613 | |||
614 | if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) { | ||
615 | if (errno == EINVAL && nrcpus < (1024 << 8)) { | ||
616 | nrcpus = nrcpus << 2; | ||
617 | goto realloc; | ||
618 | } | ||
619 | perror("sched_getaffinity"); | ||
620 | return -1; | ||
621 | } | ||
622 | |||
623 | for (i = 0; i < nrcpus; i++) { | ||
624 | if (CPU_ISSET(i, maskp)) { | ||
625 | if (cpu == -1) | ||
626 | cpu = i; | ||
627 | else | ||
628 | CPU_CLR(i, maskp); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | return cpu; | ||
633 | } | ||
634 | |||
635 | static int test__PERF_RECORD(void) | ||
636 | { | ||
637 | struct perf_record_opts opts = { | ||
638 | .target = { | ||
639 | .uid = UINT_MAX, | ||
640 | .uses_mmap = true, | ||
641 | }, | ||
642 | .no_delay = true, | ||
643 | .freq = 10, | ||
644 | .mmap_pages = 256, | ||
645 | }; | ||
646 | cpu_set_t cpu_mask; | ||
647 | size_t cpu_mask_size = sizeof(cpu_mask); | ||
648 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); | ||
649 | struct perf_evsel *evsel; | ||
650 | struct perf_sample sample; | ||
651 | const char *cmd = "sleep"; | ||
652 | const char *argv[] = { cmd, "1", NULL, }; | ||
653 | char *bname; | ||
654 | u64 prev_time = 0; | ||
655 | bool found_cmd_mmap = false, | ||
656 | found_libc_mmap = false, | ||
657 | found_vdso_mmap = false, | ||
658 | found_ld_mmap = false; | ||
659 | int err = -1, errs = 0, i, wakeups = 0; | ||
660 | u32 cpu; | ||
661 | int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; | ||
662 | |||
663 | if (evlist == NULL || argv == NULL) { | ||
664 | pr_debug("Not enough memory to create evlist\n"); | ||
665 | goto out; | ||
666 | } | ||
667 | |||
668 | /* | ||
669 | * We need at least one evsel in the evlist, use the default | ||
670 | * one: "cycles". | ||
671 | */ | ||
672 | err = perf_evlist__add_default(evlist); | ||
673 | if (err < 0) { | ||
674 | pr_debug("Not enough memory to create evsel\n"); | ||
675 | goto out_delete_evlist; | ||
676 | } | ||
677 | |||
678 | /* | ||
679 | * Create maps of threads and cpus to monitor. In this case | ||
680 | * we start with all threads and cpus (-1, -1) but then in | ||
681 | * perf_evlist__prepare_workload we'll fill in the only thread | ||
682 | * we're monitoring, the one forked there. | ||
683 | */ | ||
684 | err = perf_evlist__create_maps(evlist, &opts.target); | ||
685 | if (err < 0) { | ||
686 | pr_debug("Not enough memory to create thread/cpu maps\n"); | ||
687 | goto out_delete_evlist; | ||
688 | } | ||
689 | |||
690 | /* | ||
691 | * Prepare the workload in argv[] to run, it'll fork it, and then wait | ||
692 | * for perf_evlist__start_workload() to exec it. This is done this way | ||
693 | * so that we have time to open the evlist (calling sys_perf_event_open | ||
694 | * on all the fds) and then mmap them. | ||
695 | */ | ||
696 | err = perf_evlist__prepare_workload(evlist, &opts, argv); | ||
697 | if (err < 0) { | ||
698 | pr_debug("Couldn't run the workload!\n"); | ||
699 | goto out_delete_evlist; | ||
700 | } | ||
701 | |||
702 | /* | ||
703 | * Config the evsels, setting attr->comm on the first one, etc. | ||
704 | */ | ||
705 | evsel = perf_evlist__first(evlist); | ||
706 | evsel->attr.sample_type |= PERF_SAMPLE_CPU; | ||
707 | evsel->attr.sample_type |= PERF_SAMPLE_TID; | ||
708 | evsel->attr.sample_type |= PERF_SAMPLE_TIME; | ||
709 | perf_evlist__config_attrs(evlist, &opts); | ||
710 | |||
711 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); | ||
712 | if (err < 0) { | ||
713 | pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); | ||
714 | goto out_delete_evlist; | ||
715 | } | ||
716 | |||
717 | cpu = err; | ||
718 | |||
719 | /* | ||
720 | * So that we can check perf_sample.cpu on all the samples. | ||
721 | */ | ||
722 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { | ||
723 | pr_debug("sched_setaffinity: %s\n", strerror(errno)); | ||
724 | goto out_delete_evlist; | ||
725 | } | ||
726 | |||
727 | /* | ||
728 | * Call sys_perf_event_open on all the fds on all the evsels, | ||
729 | * grouping them if asked to. | ||
730 | */ | ||
731 | err = perf_evlist__open(evlist); | ||
732 | if (err < 0) { | ||
733 | pr_debug("perf_evlist__open: %s\n", strerror(errno)); | ||
734 | goto out_delete_evlist; | ||
735 | } | ||
736 | |||
737 | /* | ||
738 | * mmap the first fd on a given CPU and ask for events for the other | ||
739 | * fds in the same CPU to be injected in the same mmap ring buffer | ||
740 | * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)). | ||
741 | */ | ||
742 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); | ||
743 | if (err < 0) { | ||
744 | pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); | ||
745 | goto out_delete_evlist; | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * Now that all is properly set up, enable the events, they will | ||
750 | * count just on workload.pid, which will start... | ||
751 | */ | ||
752 | perf_evlist__enable(evlist); | ||
753 | |||
754 | /* | ||
755 | * Now! | ||
756 | */ | ||
757 | perf_evlist__start_workload(evlist); | ||
758 | |||
759 | while (1) { | ||
760 | int before = total_events; | ||
761 | |||
762 | for (i = 0; i < evlist->nr_mmaps; i++) { | ||
763 | union perf_event *event; | ||
764 | |||
765 | while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { | ||
766 | const u32 type = event->header.type; | ||
767 | const char *name = perf_event__name(type); | ||
768 | |||
769 | ++total_events; | ||
770 | if (type < PERF_RECORD_MAX) | ||
771 | nr_events[type]++; | ||
772 | |||
773 | err = perf_evlist__parse_sample(evlist, event, &sample); | ||
774 | if (err < 0) { | ||
775 | if (verbose) | ||
776 | perf_event__fprintf(event, stderr); | ||
777 | pr_debug("Couldn't parse sample\n"); | ||
778 | goto out_err; | ||
779 | } | ||
780 | |||
781 | if (verbose) { | ||
782 | pr_info("%" PRIu64" %d ", sample.time, sample.cpu); | ||
783 | perf_event__fprintf(event, stderr); | ||
784 | } | ||
785 | |||
786 | if (prev_time > sample.time) { | ||
787 | pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n", | ||
788 | name, prev_time, sample.time); | ||
789 | ++errs; | ||
790 | } | ||
791 | |||
792 | prev_time = sample.time; | ||
793 | |||
794 | if (sample.cpu != cpu) { | ||
795 | pr_debug("%s with unexpected cpu, expected %d, got %d\n", | ||
796 | name, cpu, sample.cpu); | ||
797 | ++errs; | ||
798 | } | ||
799 | |||
800 | if ((pid_t)sample.pid != evlist->workload.pid) { | ||
801 | pr_debug("%s with unexpected pid, expected %d, got %d\n", | ||
802 | name, evlist->workload.pid, sample.pid); | ||
803 | ++errs; | ||
804 | } | ||
805 | |||
806 | if ((pid_t)sample.tid != evlist->workload.pid) { | ||
807 | pr_debug("%s with unexpected tid, expected %d, got %d\n", | ||
808 | name, evlist->workload.pid, sample.tid); | ||
809 | ++errs; | ||
810 | } | ||
811 | |||
812 | if ((type == PERF_RECORD_COMM || | ||
813 | type == PERF_RECORD_MMAP || | ||
814 | type == PERF_RECORD_FORK || | ||
815 | type == PERF_RECORD_EXIT) && | ||
816 | (pid_t)event->comm.pid != evlist->workload.pid) { | ||
817 | pr_debug("%s with unexpected pid/tid\n", name); | ||
818 | ++errs; | ||
819 | } | ||
820 | |||
821 | if ((type == PERF_RECORD_COMM || | ||
822 | type == PERF_RECORD_MMAP) && | ||
823 | event->comm.pid != event->comm.tid) { | ||
824 | pr_debug("%s with different pid/tid!\n", name); | ||
825 | ++errs; | ||
826 | } | ||
827 | |||
828 | switch (type) { | ||
829 | case PERF_RECORD_COMM: | ||
830 | if (strcmp(event->comm.comm, cmd)) { | ||
831 | pr_debug("%s with unexpected comm!\n", name); | ||
832 | ++errs; | ||
833 | } | ||
834 | break; | ||
835 | case PERF_RECORD_EXIT: | ||
836 | goto found_exit; | ||
837 | case PERF_RECORD_MMAP: | ||
838 | bname = strrchr(event->mmap.filename, '/'); | ||
839 | if (bname != NULL) { | ||
840 | if (!found_cmd_mmap) | ||
841 | found_cmd_mmap = !strcmp(bname + 1, cmd); | ||
842 | if (!found_libc_mmap) | ||
843 | found_libc_mmap = !strncmp(bname + 1, "libc", 4); | ||
844 | if (!found_ld_mmap) | ||
845 | found_ld_mmap = !strncmp(bname + 1, "ld", 2); | ||
846 | } else if (!found_vdso_mmap) | ||
847 | found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]"); | ||
848 | break; | ||
849 | |||
850 | case PERF_RECORD_SAMPLE: | ||
851 | /* Just ignore samples for now */ | ||
852 | break; | ||
853 | default: | ||
854 | pr_debug("Unexpected perf_event->header.type %d!\n", | ||
855 | type); | ||
856 | ++errs; | ||
857 | } | ||
858 | } | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * We don't use poll here because at least at 3.1 times the | ||
863 | * PERF_RECORD_{!SAMPLE} events don't honour | ||
864 | * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. | ||
865 | */ | ||
866 | if (total_events == before && false) | ||
867 | poll(evlist->pollfd, evlist->nr_fds, -1); | ||
868 | |||
869 | sleep(1); | ||
870 | if (++wakeups > 5) { | ||
871 | pr_debug("No PERF_RECORD_EXIT event!\n"); | ||
872 | break; | ||
873 | } | ||
874 | } | ||
875 | |||
876 | found_exit: | ||
877 | if (nr_events[PERF_RECORD_COMM] > 1) { | ||
878 | pr_debug("Excessive number of PERF_RECORD_COMM events!\n"); | ||
879 | ++errs; | ||
880 | } | ||
881 | |||
882 | if (nr_events[PERF_RECORD_COMM] == 0) { | ||
883 | pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd); | ||
884 | ++errs; | ||
885 | } | ||
886 | |||
887 | if (!found_cmd_mmap) { | ||
888 | pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd); | ||
889 | ++errs; | ||
890 | } | ||
891 | |||
892 | if (!found_libc_mmap) { | ||
893 | pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc"); | ||
894 | ++errs; | ||
895 | } | ||
896 | |||
897 | if (!found_ld_mmap) { | ||
898 | pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld"); | ||
899 | ++errs; | ||
900 | } | ||
901 | |||
902 | if (!found_vdso_mmap) { | ||
903 | pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]"); | ||
904 | ++errs; | ||
905 | } | ||
906 | out_err: | ||
907 | perf_evlist__munmap(evlist); | ||
908 | out_delete_evlist: | ||
909 | perf_evlist__delete(evlist); | ||
910 | out: | ||
911 | return (err < 0 || errs > 0) ? -1 : 0; | ||
912 | } | ||
913 | |||
914 | |||
915 | #if defined(__x86_64__) || defined(__i386__) | ||
916 | |||
917 | #define barrier() asm volatile("" ::: "memory") | ||
918 | |||
919 | static u64 rdpmc(unsigned int counter) | ||
920 | { | ||
921 | unsigned int low, high; | ||
922 | |||
923 | asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter)); | ||
924 | |||
925 | return low | ((u64)high) << 32; | ||
926 | } | ||
927 | |||
928 | static u64 rdtsc(void) | ||
929 | { | ||
930 | unsigned int low, high; | ||
931 | |||
932 | asm volatile("rdtsc" : "=a" (low), "=d" (high)); | ||
933 | |||
934 | return low | ((u64)high) << 32; | ||
935 | } | ||
936 | |||
937 | static u64 mmap_read_self(void *addr) | ||
938 | { | ||
939 | struct perf_event_mmap_page *pc = addr; | ||
940 | u32 seq, idx, time_mult = 0, time_shift = 0; | ||
941 | u64 count, cyc = 0, time_offset = 0, enabled, running, delta; | ||
942 | |||
943 | do { | ||
944 | seq = pc->lock; | ||
945 | barrier(); | ||
946 | |||
947 | enabled = pc->time_enabled; | ||
948 | running = pc->time_running; | ||
949 | |||
950 | if (enabled != running) { | ||
951 | cyc = rdtsc(); | ||
952 | time_mult = pc->time_mult; | ||
953 | time_shift = pc->time_shift; | ||
954 | time_offset = pc->time_offset; | ||
955 | } | ||
956 | |||
957 | idx = pc->index; | ||
958 | count = pc->offset; | ||
959 | if (idx) | ||
960 | count += rdpmc(idx - 1); | ||
961 | |||
962 | barrier(); | ||
963 | } while (pc->lock != seq); | ||
964 | |||
965 | if (enabled != running) { | ||
966 | u64 quot, rem; | ||
967 | |||
968 | quot = (cyc >> time_shift); | ||
969 | rem = cyc & ((1 << time_shift) - 1); | ||
970 | delta = time_offset + quot * time_mult + | ||
971 | ((rem * time_mult) >> time_shift); | ||
972 | |||
973 | enabled += delta; | ||
974 | if (idx) | ||
975 | running += delta; | ||
976 | |||
977 | quot = count / running; | ||
978 | rem = count % running; | ||
979 | count = quot * enabled + (rem * enabled) / running; | ||
980 | } | ||
981 | |||
982 | return count; | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * If the RDPMC instruction faults then signal this back to the test parent task: | ||
987 | */ | ||
988 | static void segfault_handler(int sig __maybe_unused, | ||
989 | siginfo_t *info __maybe_unused, | ||
990 | void *uc __maybe_unused) | ||
991 | { | ||
992 | exit(-1); | ||
993 | } | ||
994 | |||
995 | static int __test__rdpmc(void) | ||
996 | { | ||
997 | volatile int tmp = 0; | ||
998 | u64 i, loops = 1000; | ||
999 | int n; | ||
1000 | int fd; | ||
1001 | void *addr; | ||
1002 | struct perf_event_attr attr = { | ||
1003 | .type = PERF_TYPE_HARDWARE, | ||
1004 | .config = PERF_COUNT_HW_INSTRUCTIONS, | ||
1005 | .exclude_kernel = 1, | ||
1006 | }; | ||
1007 | u64 delta_sum = 0; | ||
1008 | struct sigaction sa; | ||
1009 | |||
1010 | sigfillset(&sa.sa_mask); | ||
1011 | sa.sa_sigaction = segfault_handler; | ||
1012 | sigaction(SIGSEGV, &sa, NULL); | ||
1013 | |||
1014 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | ||
1015 | if (fd < 0) { | ||
1016 | pr_err("Error: sys_perf_event_open() syscall returned " | ||
1017 | "with %d (%s)\n", fd, strerror(errno)); | ||
1018 | return -1; | ||
1019 | } | ||
1020 | |||
1021 | addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); | ||
1022 | if (addr == (void *)(-1)) { | ||
1023 | pr_err("Error: mmap() syscall returned with (%s)\n", | ||
1024 | strerror(errno)); | ||
1025 | goto out_close; | ||
1026 | } | ||
1027 | |||
1028 | for (n = 0; n < 6; n++) { | ||
1029 | u64 stamp, now, delta; | ||
1030 | |||
1031 | stamp = mmap_read_self(addr); | ||
1032 | |||
1033 | for (i = 0; i < loops; i++) | ||
1034 | tmp++; | ||
1035 | |||
1036 | now = mmap_read_self(addr); | ||
1037 | loops *= 10; | ||
1038 | |||
1039 | delta = now - stamp; | ||
1040 | pr_debug("%14d: %14Lu\n", n, (long long)delta); | ||
1041 | |||
1042 | delta_sum += delta; | ||
1043 | } | ||
1044 | |||
1045 | munmap(addr, page_size); | ||
1046 | pr_debug(" "); | ||
1047 | out_close: | ||
1048 | close(fd); | ||
1049 | |||
1050 | if (!delta_sum) | ||
1051 | return -1; | ||
1052 | |||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | static int test__rdpmc(void) | ||
1057 | { | ||
1058 | int status = 0; | ||
1059 | int wret = 0; | ||
1060 | int ret; | ||
1061 | int pid; | ||
1062 | |||
1063 | pid = fork(); | ||
1064 | if (pid < 0) | ||
1065 | return -1; | ||
1066 | |||
1067 | if (!pid) { | ||
1068 | ret = __test__rdpmc(); | ||
1069 | |||
1070 | exit(ret); | ||
1071 | } | ||
1072 | |||
1073 | wret = waitpid(pid, &status, 0); | ||
1074 | if (wret < 0 || status) | ||
1075 | return -1; | ||
1076 | |||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | #endif | ||
1081 | |||
1082 | static int test__perf_pmu(void) | ||
1083 | { | ||
1084 | return perf_pmu__test(); | ||
1085 | } | ||
1086 | |||
1087 | static int perf_evsel__roundtrip_cache_name_test(void) | ||
1088 | { | ||
1089 | char name[128]; | ||
1090 | int type, op, err = 0, ret = 0, i, idx; | ||
1091 | struct perf_evsel *evsel; | ||
1092 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); | ||
1093 | |||
1094 | if (evlist == NULL) | ||
1095 | return -ENOMEM; | ||
1096 | |||
1097 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { | ||
1098 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { | ||
1099 | /* skip invalid cache type */ | ||
1100 | if (!perf_evsel__is_cache_op_valid(type, op)) | ||
1101 | continue; | ||
1102 | |||
1103 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { | ||
1104 | __perf_evsel__hw_cache_type_op_res_name(type, op, i, | ||
1105 | name, sizeof(name)); | ||
1106 | err = parse_events(evlist, name, 0); | ||
1107 | if (err) | ||
1108 | ret = err; | ||
1109 | } | ||
1110 | } | ||
1111 | } | ||
1112 | |||
1113 | idx = 0; | ||
1114 | evsel = perf_evlist__first(evlist); | ||
1115 | |||
1116 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { | ||
1117 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { | ||
1118 | /* skip invalid cache type */ | ||
1119 | if (!perf_evsel__is_cache_op_valid(type, op)) | ||
1120 | continue; | ||
1121 | |||
1122 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { | ||
1123 | __perf_evsel__hw_cache_type_op_res_name(type, op, i, | ||
1124 | name, sizeof(name)); | ||
1125 | if (evsel->idx != idx) | ||
1126 | continue; | ||
1127 | |||
1128 | ++idx; | ||
1129 | |||
1130 | if (strcmp(perf_evsel__name(evsel), name)) { | ||
1131 | pr_debug("%s != %s\n", perf_evsel__name(evsel), name); | ||
1132 | ret = -1; | ||
1133 | } | ||
1134 | |||
1135 | evsel = perf_evsel__next(evsel); | ||
1136 | } | ||
1137 | } | ||
1138 | } | ||
1139 | |||
1140 | perf_evlist__delete(evlist); | ||
1141 | return ret; | ||
1142 | } | ||
1143 | |||
1144 | static int __perf_evsel__name_array_test(const char *names[], int nr_names) | ||
1145 | { | ||
1146 | int i, err; | ||
1147 | struct perf_evsel *evsel; | ||
1148 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); | ||
1149 | |||
1150 | if (evlist == NULL) | ||
1151 | return -ENOMEM; | ||
1152 | |||
1153 | for (i = 0; i < nr_names; ++i) { | ||
1154 | err = parse_events(evlist, names[i], 0); | ||
1155 | if (err) { | ||
1156 | pr_debug("failed to parse event '%s', err %d\n", | ||
1157 | names[i], err); | ||
1158 | goto out_delete_evlist; | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | err = 0; | ||
1163 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
1164 | if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { | ||
1165 | --err; | ||
1166 | pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | out_delete_evlist: | ||
1171 | perf_evlist__delete(evlist); | ||
1172 | return err; | ||
1173 | } | ||
1174 | |||
1175 | #define perf_evsel__name_array_test(names) \ | ||
1176 | __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) | ||
1177 | |||
1178 | static int perf_evsel__roundtrip_name_test(void) | ||
1179 | { | ||
1180 | int err = 0, ret = 0; | ||
1181 | |||
1182 | err = perf_evsel__name_array_test(perf_evsel__hw_names); | ||
1183 | if (err) | ||
1184 | ret = err; | ||
1185 | |||
1186 | err = perf_evsel__name_array_test(perf_evsel__sw_names); | ||
1187 | if (err) | ||
1188 | ret = err; | ||
1189 | |||
1190 | err = perf_evsel__roundtrip_cache_name_test(); | ||
1191 | if (err) | ||
1192 | ret = err; | ||
1193 | |||
1194 | return ret; | ||
1195 | } | ||
1196 | |||
1197 | static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, | ||
1198 | int size, bool should_be_signed) | ||
1199 | { | ||
1200 | struct format_field *field = perf_evsel__field(evsel, name); | ||
1201 | int is_signed; | ||
1202 | int ret = 0; | ||
1203 | |||
1204 | if (field == NULL) { | ||
1205 | pr_debug("%s: \"%s\" field not found!\n", evsel->name, name); | ||
1206 | return -1; | ||
1207 | } | ||
1208 | |||
1209 | is_signed = !!(field->flags | FIELD_IS_SIGNED); | ||
1210 | if (should_be_signed && !is_signed) { | ||
1211 | pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", | ||
1212 | evsel->name, name, is_signed, should_be_signed); | ||
1213 | ret = -1; | ||
1214 | } | ||
1215 | |||
1216 | if (field->size != size) { | ||
1217 | pr_debug("%s: \"%s\" size (%d) should be %d!\n", | ||
1218 | evsel->name, name, field->size, size); | ||
1219 | ret = -1; | ||
1220 | } | ||
1221 | |||
1222 | return ret; | ||
1223 | } | ||
1224 | |||
1225 | static int perf_evsel__tp_sched_test(void) | ||
1226 | { | ||
1227 | struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); | ||
1228 | int ret = 0; | ||
1229 | |||
1230 | if (evsel == NULL) { | ||
1231 | pr_debug("perf_evsel__new\n"); | ||
1232 | return -1; | ||
1233 | } | ||
1234 | |||
1235 | if (perf_evsel__test_field(evsel, "prev_comm", 16, true)) | ||
1236 | ret = -1; | ||
1237 | |||
1238 | if (perf_evsel__test_field(evsel, "prev_pid", 4, true)) | ||
1239 | ret = -1; | ||
1240 | |||
1241 | if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) | ||
1242 | ret = -1; | ||
1243 | |||
1244 | if (perf_evsel__test_field(evsel, "prev_state", 8, true)) | ||
1245 | ret = -1; | ||
1246 | |||
1247 | if (perf_evsel__test_field(evsel, "next_comm", 16, true)) | ||
1248 | ret = -1; | ||
1249 | |||
1250 | if (perf_evsel__test_field(evsel, "next_pid", 4, true)) | ||
1251 | ret = -1; | ||
1252 | |||
1253 | if (perf_evsel__test_field(evsel, "next_prio", 4, true)) | ||
1254 | ret = -1; | ||
1255 | |||
1256 | perf_evsel__delete(evsel); | ||
1257 | |||
1258 | evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); | ||
1259 | |||
1260 | if (perf_evsel__test_field(evsel, "comm", 16, true)) | ||
1261 | ret = -1; | ||
1262 | |||
1263 | if (perf_evsel__test_field(evsel, "pid", 4, true)) | ||
1264 | ret = -1; | ||
1265 | |||
1266 | if (perf_evsel__test_field(evsel, "prio", 4, true)) | ||
1267 | ret = -1; | ||
1268 | |||
1269 | if (perf_evsel__test_field(evsel, "success", 4, true)) | ||
1270 | ret = -1; | ||
1271 | |||
1272 | if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) | ||
1273 | ret = -1; | ||
1274 | |||
1275 | return ret; | ||
1276 | } | ||
1277 | |||
1278 | static int test__syscall_open_tp_fields(void) | ||
1279 | { | ||
1280 | struct perf_record_opts opts = { | ||
1281 | .target = { | ||
1282 | .uid = UINT_MAX, | ||
1283 | .uses_mmap = true, | ||
1284 | }, | ||
1285 | .no_delay = true, | ||
1286 | .freq = 1, | ||
1287 | .mmap_pages = 256, | ||
1288 | .raw_samples = true, | ||
1289 | }; | ||
1290 | const char *filename = "/etc/passwd"; | ||
1291 | int flags = O_RDONLY | O_DIRECTORY; | ||
1292 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); | ||
1293 | struct perf_evsel *evsel; | ||
1294 | int err = -1, i, nr_events = 0, nr_polls = 0; | ||
1295 | |||
1296 | if (evlist == NULL) { | ||
1297 | pr_debug("%s: perf_evlist__new\n", __func__); | ||
1298 | goto out; | ||
1299 | } | ||
1300 | |||
1301 | evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); | ||
1302 | if (evsel == NULL) { | ||
1303 | pr_debug("%s: perf_evsel__newtp\n", __func__); | ||
1304 | goto out_delete_evlist; | ||
1305 | } | ||
1306 | |||
1307 | perf_evlist__add(evlist, evsel); | ||
1308 | |||
1309 | err = perf_evlist__create_maps(evlist, &opts.target); | ||
1310 | if (err < 0) { | ||
1311 | pr_debug("%s: perf_evlist__create_maps\n", __func__); | ||
1312 | goto out_delete_evlist; | ||
1313 | } | ||
1314 | |||
1315 | perf_evsel__config(evsel, &opts, evsel); | ||
1316 | |||
1317 | evlist->threads->map[0] = getpid(); | ||
1318 | |||
1319 | err = perf_evlist__open(evlist); | ||
1320 | if (err < 0) { | ||
1321 | pr_debug("perf_evlist__open: %s\n", strerror(errno)); | ||
1322 | goto out_delete_evlist; | ||
1323 | } | ||
1324 | |||
1325 | err = perf_evlist__mmap(evlist, UINT_MAX, false); | ||
1326 | if (err < 0) { | ||
1327 | pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); | ||
1328 | goto out_delete_evlist; | ||
1329 | } | ||
1330 | |||
1331 | perf_evlist__enable(evlist); | ||
1332 | |||
1333 | /* | ||
1334 | * Generate the event: | ||
1335 | */ | ||
1336 | open(filename, flags); | ||
1337 | |||
1338 | while (1) { | ||
1339 | int before = nr_events; | ||
1340 | |||
1341 | for (i = 0; i < evlist->nr_mmaps; i++) { | ||
1342 | union perf_event *event; | ||
1343 | |||
1344 | while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { | ||
1345 | const u32 type = event->header.type; | ||
1346 | int tp_flags; | ||
1347 | struct perf_sample sample; | ||
1348 | |||
1349 | ++nr_events; | ||
1350 | |||
1351 | if (type != PERF_RECORD_SAMPLE) | ||
1352 | continue; | ||
1353 | |||
1354 | err = perf_evsel__parse_sample(evsel, event, &sample); | ||
1355 | if (err) { | ||
1356 | pr_err("Can't parse sample, err = %d\n", err); | ||
1357 | goto out_munmap; | ||
1358 | } | ||
1359 | |||
1360 | tp_flags = perf_evsel__intval(evsel, &sample, "flags"); | ||
1361 | |||
1362 | if (flags != tp_flags) { | ||
1363 | pr_debug("%s: Expected flags=%#x, got %#x\n", | ||
1364 | __func__, flags, tp_flags); | ||
1365 | goto out_munmap; | ||
1366 | } | ||
1367 | |||
1368 | goto out_ok; | ||
1369 | } | ||
1370 | } | ||
1371 | |||
1372 | if (nr_events == before) | ||
1373 | poll(evlist->pollfd, evlist->nr_fds, 10); | ||
1374 | |||
1375 | if (++nr_polls > 5) { | ||
1376 | pr_debug("%s: no events!\n", __func__); | ||
1377 | goto out_munmap; | ||
1378 | } | ||
1379 | } | ||
1380 | out_ok: | ||
1381 | err = 0; | ||
1382 | out_munmap: | ||
1383 | perf_evlist__munmap(evlist); | ||
1384 | out_delete_evlist: | ||
1385 | perf_evlist__delete(evlist); | ||
1386 | out: | ||
1387 | return err; | ||
1388 | } | ||
1389 | |||
1390 | static struct test { | ||
1391 | const char *desc; | ||
1392 | int (*func)(void); | ||
1393 | } tests[] = { | ||
1394 | { | ||
1395 | .desc = "vmlinux symtab matches kallsyms", | ||
1396 | .func = test__vmlinux_matches_kallsyms, | ||
1397 | }, | ||
1398 | { | ||
1399 | .desc = "detect open syscall event", | ||
1400 | .func = test__open_syscall_event, | ||
1401 | }, | ||
1402 | { | ||
1403 | .desc = "detect open syscall event on all cpus", | ||
1404 | .func = test__open_syscall_event_on_all_cpus, | ||
1405 | }, | ||
1406 | { | ||
1407 | .desc = "read samples using the mmap interface", | ||
1408 | .func = test__basic_mmap, | ||
1409 | }, | ||
1410 | { | ||
1411 | .desc = "parse events tests", | ||
1412 | .func = parse_events__test, | ||
1413 | }, | ||
1414 | #if defined(__x86_64__) || defined(__i386__) | ||
1415 | { | ||
1416 | .desc = "x86 rdpmc test", | ||
1417 | .func = test__rdpmc, | ||
1418 | }, | ||
1419 | #endif | ||
1420 | { | ||
1421 | .desc = "Validate PERF_RECORD_* events & perf_sample fields", | ||
1422 | .func = test__PERF_RECORD, | ||
1423 | }, | ||
1424 | { | ||
1425 | .desc = "Test perf pmu format parsing", | ||
1426 | .func = test__perf_pmu, | ||
1427 | }, | ||
1428 | { | ||
1429 | .desc = "Test dso data interface", | ||
1430 | .func = dso__test_data, | ||
1431 | }, | ||
1432 | { | ||
1433 | .desc = "roundtrip evsel->name check", | ||
1434 | .func = perf_evsel__roundtrip_name_test, | ||
1435 | }, | ||
1436 | { | ||
1437 | .desc = "Check parsing of sched tracepoints fields", | ||
1438 | .func = perf_evsel__tp_sched_test, | ||
1439 | }, | ||
1440 | { | ||
1441 | .desc = "Generate and check syscalls:sys_enter_open event fields", | ||
1442 | .func = test__syscall_open_tp_fields, | ||
1443 | }, | ||
1444 | { | ||
1445 | .desc = "struct perf_event_attr setup", | ||
1446 | .func = test_attr__run, | ||
1447 | }, | ||
1448 | { | ||
1449 | .func = NULL, | ||
1450 | }, | ||
1451 | }; | ||
1452 | |||
1453 | static bool perf_test__matches(int curr, int argc, const char *argv[]) | ||
1454 | { | ||
1455 | int i; | ||
1456 | |||
1457 | if (argc == 0) | ||
1458 | return true; | ||
1459 | |||
1460 | for (i = 0; i < argc; ++i) { | ||
1461 | char *end; | ||
1462 | long nr = strtoul(argv[i], &end, 10); | ||
1463 | |||
1464 | if (*end == '\0') { | ||
1465 | if (nr == curr + 1) | ||
1466 | return true; | ||
1467 | continue; | ||
1468 | } | ||
1469 | |||
1470 | if (strstr(tests[curr].desc, argv[i])) | ||
1471 | return true; | ||
1472 | } | ||
1473 | |||
1474 | return false; | ||
1475 | } | ||
1476 | |||
1477 | static int __cmd_test(int argc, const char *argv[]) | ||
1478 | { | ||
1479 | int i = 0; | ||
1480 | int width = 0; | ||
1481 | |||
1482 | while (tests[i].func) { | ||
1483 | int len = strlen(tests[i].desc); | ||
1484 | |||
1485 | if (width < len) | ||
1486 | width = len; | ||
1487 | ++i; | ||
1488 | } | ||
1489 | |||
1490 | i = 0; | ||
1491 | while (tests[i].func) { | ||
1492 | int curr = i++, err; | ||
1493 | |||
1494 | if (!perf_test__matches(curr, argc, argv)) | ||
1495 | continue; | ||
1496 | |||
1497 | pr_info("%2d: %-*s:", i, width, tests[curr].desc); | ||
1498 | pr_debug("\n--- start ---\n"); | ||
1499 | err = tests[curr].func(); | ||
1500 | pr_debug("---- end ----\n%s:", tests[curr].desc); | ||
1501 | if (err) | ||
1502 | color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n"); | ||
1503 | else | ||
1504 | pr_info(" Ok\n"); | ||
1505 | } | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1509 | |||
1510 | static int perf_test__list(int argc, const char **argv) | ||
1511 | { | ||
1512 | int i = 0; | ||
1513 | |||
1514 | while (tests[i].func) { | ||
1515 | int curr = i++; | ||
1516 | |||
1517 | if (argc > 1 && !strstr(tests[curr].desc, argv[1])) | ||
1518 | continue; | ||
1519 | |||
1520 | pr_info("%2d: %s\n", i, tests[curr].desc); | ||
1521 | } | ||
1522 | |||
1523 | return 0; | ||
1524 | } | ||
1525 | |||
1526 | int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) | ||
1527 | { | ||
1528 | const char * const test_usage[] = { | ||
1529 | "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", | ||
1530 | NULL, | ||
1531 | }; | ||
1532 | const struct option test_options[] = { | ||
1533 | OPT_INCR('v', "verbose", &verbose, | ||
1534 | "be more verbose (show symbol address, etc)"), | ||
1535 | OPT_END() | ||
1536 | }; | ||
1537 | |||
1538 | argc = parse_options(argc, argv, test_options, test_usage, 0); | ||
1539 | if (argc >= 1 && !strcmp(argv[0], "list")) | ||
1540 | return perf_test__list(argc, argv); | ||
1541 | |||
1542 | symbol_conf.priv_size = sizeof(int); | ||
1543 | symbol_conf.sort_by_name = true; | ||
1544 | symbol_conf.try_vmlinux_path = true; | ||
1545 | |||
1546 | if (symbol__init() < 0) | ||
1547 | return -1; | ||
1548 | |||
1549 | return __cmd_test(argc, argv); | ||
1550 | } | ||
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c new file mode 100644 index 000000000000..0cd42fc9bc13 --- /dev/null +++ b/tools/perf/tests/dso-data.c | |||
@@ -0,0 +1,154 @@ | |||
1 | #include "util.h" | ||
2 | |||
3 | #include <stdlib.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/stat.h> | ||
6 | #include <fcntl.h> | ||
7 | #include <string.h> | ||
8 | |||
9 | #include "machine.h" | ||
10 | #include "symbol.h" | ||
11 | |||
12 | #define TEST_ASSERT_VAL(text, cond) \ | ||
13 | do { \ | ||
14 | if (!(cond)) { \ | ||
15 | pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ | ||
16 | return -1; \ | ||
17 | } \ | ||
18 | } while (0) | ||
19 | |||
20 | static char *test_file(int size) | ||
21 | { | ||
22 | static char buf_templ[] = "/tmp/test-XXXXXX"; | ||
23 | char *templ = buf_templ; | ||
24 | int fd, i; | ||
25 | unsigned char *buf; | ||
26 | |||
27 | fd = mkstemp(templ); | ||
28 | |||
29 | buf = malloc(size); | ||
30 | if (!buf) { | ||
31 | close(fd); | ||
32 | return NULL; | ||
33 | } | ||
34 | |||
35 | for (i = 0; i < size; i++) | ||
36 | buf[i] = (unsigned char) ((int) i % 10); | ||
37 | |||
38 | if (size != write(fd, buf, size)) | ||
39 | templ = NULL; | ||
40 | |||
41 | close(fd); | ||
42 | return templ; | ||
43 | } | ||
44 | |||
45 | #define TEST_FILE_SIZE (DSO__DATA_CACHE_SIZE * 20) | ||
46 | |||
47 | struct test_data_offset { | ||
48 | off_t offset; | ||
49 | u8 data[10]; | ||
50 | int size; | ||
51 | }; | ||
52 | |||
53 | struct test_data_offset offsets[] = { | ||
54 | /* Fill first cache page. */ | ||
55 | { | ||
56 | .offset = 10, | ||
57 | .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
58 | .size = 10, | ||
59 | }, | ||
60 | /* Read first cache page. */ | ||
61 | { | ||
62 | .offset = 10, | ||
63 | .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
64 | .size = 10, | ||
65 | }, | ||
66 | /* Fill cache boundary pages. */ | ||
67 | { | ||
68 | .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10, | ||
69 | .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
70 | .size = 10, | ||
71 | }, | ||
72 | /* Read cache boundary pages. */ | ||
73 | { | ||
74 | .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10, | ||
75 | .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
76 | .size = 10, | ||
77 | }, | ||
78 | /* Fill final cache page. */ | ||
79 | { | ||
80 | .offset = TEST_FILE_SIZE - 10, | ||
81 | .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
82 | .size = 10, | ||
83 | }, | ||
84 | /* Read final cache page. */ | ||
85 | { | ||
86 | .offset = TEST_FILE_SIZE - 10, | ||
87 | .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
88 | .size = 10, | ||
89 | }, | ||
90 | /* Read final cache page. */ | ||
91 | { | ||
92 | .offset = TEST_FILE_SIZE - 3, | ||
93 | .data = { 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 }, | ||
94 | .size = 3, | ||
95 | }, | ||
96 | }; | ||
97 | |||
98 | int dso__test_data(void) | ||
99 | { | ||
100 | struct machine machine; | ||
101 | struct dso *dso; | ||
102 | char *file = test_file(TEST_FILE_SIZE); | ||
103 | size_t i; | ||
104 | |||
105 | TEST_ASSERT_VAL("No test file", file); | ||
106 | |||
107 | memset(&machine, 0, sizeof(machine)); | ||
108 | |||
109 | dso = dso__new((const char *)file); | ||
110 | |||
111 | /* Basic 10 bytes tests. */ | ||
112 | for (i = 0; i < ARRAY_SIZE(offsets); i++) { | ||
113 | struct test_data_offset *data = &offsets[i]; | ||
114 | ssize_t size; | ||
115 | u8 buf[10]; | ||
116 | |||
117 | memset(buf, 0, 10); | ||
118 | size = dso__data_read_offset(dso, &machine, data->offset, | ||
119 | buf, 10); | ||
120 | |||
121 | TEST_ASSERT_VAL("Wrong size", size == data->size); | ||
122 | TEST_ASSERT_VAL("Wrong data", !memcmp(buf, data->data, 10)); | ||
123 | } | ||
124 | |||
125 | /* Read cross multiple cache pages. */ | ||
126 | { | ||
127 | ssize_t size; | ||
128 | int c; | ||
129 | u8 *buf; | ||
130 | |||
131 | buf = malloc(TEST_FILE_SIZE); | ||
132 | TEST_ASSERT_VAL("ENOMEM\n", buf); | ||
133 | |||
134 | /* First iteration to fill caches, second one to read them. */ | ||
135 | for (c = 0; c < 2; c++) { | ||
136 | memset(buf, 0, TEST_FILE_SIZE); | ||
137 | size = dso__data_read_offset(dso, &machine, 10, | ||
138 | buf, TEST_FILE_SIZE); | ||
139 | |||
140 | TEST_ASSERT_VAL("Wrong size", | ||
141 | size == (TEST_FILE_SIZE - 10)); | ||
142 | |||
143 | for (i = 0; i < (size_t)size; i++) | ||
144 | TEST_ASSERT_VAL("Wrong data", | ||
145 | buf[i] == (i % 10)); | ||
146 | } | ||
147 | |||
148 | free(buf); | ||
149 | } | ||
150 | |||
151 | dso__delete(dso); | ||
152 | unlink(file); | ||
153 | return 0; | ||
154 | } | ||
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c new file mode 100644 index 000000000000..b49c2eebff33 --- /dev/null +++ b/tools/perf/tests/parse-events.c | |||
@@ -0,0 +1,1116 @@ | |||
1 | |||
2 | #include "parse-events.h" | ||
3 | #include "evsel.h" | ||
4 | #include "evlist.h" | ||
5 | #include "sysfs.h" | ||
6 | #include "../../../include/linux/hw_breakpoint.h" | ||
7 | |||
8 | #define TEST_ASSERT_VAL(text, cond) \ | ||
9 | do { \ | ||
10 | if (!(cond)) { \ | ||
11 | pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ | ||
12 | return -1; \ | ||
13 | } \ | ||
14 | } while (0) | ||
15 | |||
16 | #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ | ||
17 | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) | ||
18 | |||
19 | static int test__checkevent_tracepoint(struct perf_evlist *evlist) | ||
20 | { | ||
21 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
22 | |||
23 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
24 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); | ||
25 | TEST_ASSERT_VAL("wrong sample_type", | ||
26 | PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); | ||
27 | TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) | ||
32 | { | ||
33 | struct perf_evsel *evsel; | ||
34 | |||
35 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); | ||
36 | |||
37 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
38 | TEST_ASSERT_VAL("wrong type", | ||
39 | PERF_TYPE_TRACEPOINT == evsel->attr.type); | ||
40 | TEST_ASSERT_VAL("wrong sample_type", | ||
41 | PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); | ||
42 | TEST_ASSERT_VAL("wrong sample_period", | ||
43 | 1 == evsel->attr.sample_period); | ||
44 | } | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static int test__checkevent_raw(struct perf_evlist *evlist) | ||
49 | { | ||
50 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
51 | |||
52 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
53 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); | ||
54 | TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int test__checkevent_numeric(struct perf_evlist *evlist) | ||
59 | { | ||
60 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
61 | |||
62 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
63 | TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); | ||
64 | TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int test__checkevent_symbolic_name(struct perf_evlist *evlist) | ||
69 | { | ||
70 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
71 | |||
72 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
73 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
74 | TEST_ASSERT_VAL("wrong config", | ||
75 | PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) | ||
80 | { | ||
81 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
82 | |||
83 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
84 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
85 | TEST_ASSERT_VAL("wrong config", | ||
86 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
87 | TEST_ASSERT_VAL("wrong period", | ||
88 | 100000 == evsel->attr.sample_period); | ||
89 | TEST_ASSERT_VAL("wrong config1", | ||
90 | 0 == evsel->attr.config1); | ||
91 | TEST_ASSERT_VAL("wrong config2", | ||
92 | 1 == evsel->attr.config2); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) | ||
97 | { | ||
98 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
99 | |||
100 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
101 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); | ||
102 | TEST_ASSERT_VAL("wrong config", | ||
103 | PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int test__checkevent_genhw(struct perf_evlist *evlist) | ||
108 | { | ||
109 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
110 | |||
111 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
112 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); | ||
113 | TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int test__checkevent_breakpoint(struct perf_evlist *evlist) | ||
118 | { | ||
119 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
120 | |||
121 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
122 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
123 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
124 | TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == | ||
125 | evsel->attr.bp_type); | ||
126 | TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 == | ||
127 | evsel->attr.bp_len); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) | ||
132 | { | ||
133 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
134 | |||
135 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
136 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
137 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
138 | TEST_ASSERT_VAL("wrong bp_type", | ||
139 | HW_BREAKPOINT_X == evsel->attr.bp_type); | ||
140 | TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) | ||
145 | { | ||
146 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
147 | |||
148 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
149 | TEST_ASSERT_VAL("wrong type", | ||
150 | PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
151 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
152 | TEST_ASSERT_VAL("wrong bp_type", | ||
153 | HW_BREAKPOINT_R == evsel->attr.bp_type); | ||
154 | TEST_ASSERT_VAL("wrong bp_len", | ||
155 | HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) | ||
160 | { | ||
161 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
162 | |||
163 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
164 | TEST_ASSERT_VAL("wrong type", | ||
165 | PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
166 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
167 | TEST_ASSERT_VAL("wrong bp_type", | ||
168 | HW_BREAKPOINT_W == evsel->attr.bp_type); | ||
169 | TEST_ASSERT_VAL("wrong bp_len", | ||
170 | HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) | ||
175 | { | ||
176 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
177 | |||
178 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
179 | TEST_ASSERT_VAL("wrong type", | ||
180 | PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
181 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
182 | TEST_ASSERT_VAL("wrong bp_type", | ||
183 | (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type); | ||
184 | TEST_ASSERT_VAL("wrong bp_len", | ||
185 | HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) | ||
190 | { | ||
191 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
192 | |||
193 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
194 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
195 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
196 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
197 | |||
198 | return test__checkevent_tracepoint(evlist); | ||
199 | } | ||
200 | |||
201 | static int | ||
202 | test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) | ||
203 | { | ||
204 | struct perf_evsel *evsel; | ||
205 | |||
206 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); | ||
207 | |||
208 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
209 | TEST_ASSERT_VAL("wrong exclude_user", | ||
210 | !evsel->attr.exclude_user); | ||
211 | TEST_ASSERT_VAL("wrong exclude_kernel", | ||
212 | evsel->attr.exclude_kernel); | ||
213 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
214 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
215 | } | ||
216 | |||
217 | return test__checkevent_tracepoint_multi(evlist); | ||
218 | } | ||
219 | |||
220 | static int test__checkevent_raw_modifier(struct perf_evlist *evlist) | ||
221 | { | ||
222 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
223 | |||
224 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
225 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
226 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
227 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
228 | |||
229 | return test__checkevent_raw(evlist); | ||
230 | } | ||
231 | |||
232 | static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) | ||
233 | { | ||
234 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
235 | |||
236 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
237 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
238 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
239 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
240 | |||
241 | return test__checkevent_numeric(evlist); | ||
242 | } | ||
243 | |||
244 | static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) | ||
245 | { | ||
246 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
247 | |||
248 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
249 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
250 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
251 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
252 | |||
253 | return test__checkevent_symbolic_name(evlist); | ||
254 | } | ||
255 | |||
256 | static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) | ||
257 | { | ||
258 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
259 | |||
260 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
261 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
262 | |||
263 | return test__checkevent_symbolic_name(evlist); | ||
264 | } | ||
265 | |||
266 | static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) | ||
267 | { | ||
268 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
269 | |||
270 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
271 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
272 | |||
273 | return test__checkevent_symbolic_name(evlist); | ||
274 | } | ||
275 | |||
276 | static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) | ||
277 | { | ||
278 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
279 | |||
280 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
281 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
282 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
283 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
284 | |||
285 | return test__checkevent_symbolic_alias(evlist); | ||
286 | } | ||
287 | |||
288 | static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) | ||
289 | { | ||
290 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
291 | |||
292 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
293 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
294 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
295 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
296 | |||
297 | return test__checkevent_genhw(evlist); | ||
298 | } | ||
299 | |||
300 | static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) | ||
301 | { | ||
302 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
303 | |||
304 | |||
305 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
306 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
307 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
308 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
309 | TEST_ASSERT_VAL("wrong name", | ||
310 | !strcmp(perf_evsel__name(evsel), "mem:0:u")); | ||
311 | |||
312 | return test__checkevent_breakpoint(evlist); | ||
313 | } | ||
314 | |||
315 | static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) | ||
316 | { | ||
317 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
318 | |||
319 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
320 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
321 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
322 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
323 | TEST_ASSERT_VAL("wrong name", | ||
324 | !strcmp(perf_evsel__name(evsel), "mem:0:x:k")); | ||
325 | |||
326 | return test__checkevent_breakpoint_x(evlist); | ||
327 | } | ||
328 | |||
329 | static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) | ||
330 | { | ||
331 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
332 | |||
333 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
334 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
335 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
336 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
337 | TEST_ASSERT_VAL("wrong name", | ||
338 | !strcmp(perf_evsel__name(evsel), "mem:0:r:hp")); | ||
339 | |||
340 | return test__checkevent_breakpoint_r(evlist); | ||
341 | } | ||
342 | |||
343 | static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) | ||
344 | { | ||
345 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
346 | |||
347 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
348 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
349 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
350 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
351 | TEST_ASSERT_VAL("wrong name", | ||
352 | !strcmp(perf_evsel__name(evsel), "mem:0:w:up")); | ||
353 | |||
354 | return test__checkevent_breakpoint_w(evlist); | ||
355 | } | ||
356 | |||
357 | static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) | ||
358 | { | ||
359 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
360 | |||
361 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
362 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
363 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
364 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
365 | TEST_ASSERT_VAL("wrong name", | ||
366 | !strcmp(perf_evsel__name(evsel), "mem:0:rw:kp")); | ||
367 | |||
368 | return test__checkevent_breakpoint_rw(evlist); | ||
369 | } | ||
370 | |||
371 | static int test__checkevent_pmu(struct perf_evlist *evlist) | ||
372 | { | ||
373 | |||
374 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
375 | |||
376 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
377 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); | ||
378 | TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config); | ||
379 | TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1); | ||
380 | TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2); | ||
381 | TEST_ASSERT_VAL("wrong period", 1000 == evsel->attr.sample_period); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int test__checkevent_list(struct perf_evlist *evlist) | ||
387 | { | ||
388 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
389 | |||
390 | TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); | ||
391 | |||
392 | /* r1 */ | ||
393 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); | ||
394 | TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); | ||
395 | TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1); | ||
396 | TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2); | ||
397 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
398 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
399 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
400 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
401 | |||
402 | /* syscalls:sys_enter_open:k */ | ||
403 | evsel = perf_evsel__next(evsel); | ||
404 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); | ||
405 | TEST_ASSERT_VAL("wrong sample_type", | ||
406 | PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); | ||
407 | TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); | ||
408 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
409 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
410 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
411 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
412 | |||
413 | /* 1:1:hp */ | ||
414 | evsel = perf_evsel__next(evsel); | ||
415 | TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); | ||
416 | TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); | ||
417 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
418 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
419 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
420 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int test__checkevent_pmu_name(struct perf_evlist *evlist) | ||
426 | { | ||
427 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
428 | |||
429 | /* cpu/config=1,name=krava/u */ | ||
430 | TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); | ||
431 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); | ||
432 | TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); | ||
433 | TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava")); | ||
434 | |||
435 | /* cpu/config=2/u" */ | ||
436 | evsel = perf_evsel__next(evsel); | ||
437 | TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); | ||
438 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); | ||
439 | TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); | ||
440 | TEST_ASSERT_VAL("wrong name", | ||
441 | !strcmp(perf_evsel__name(evsel), "cpu/config=2/u")); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int test__checkevent_pmu_events(struct perf_evlist *evlist) | ||
447 | { | ||
448 | struct perf_evsel *evsel; | ||
449 | |||
450 | evsel = list_entry(evlist->entries.next, struct perf_evsel, node); | ||
451 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
452 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); | ||
453 | TEST_ASSERT_VAL("wrong exclude_user", | ||
454 | !evsel->attr.exclude_user); | ||
455 | TEST_ASSERT_VAL("wrong exclude_kernel", | ||
456 | evsel->attr.exclude_kernel); | ||
457 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
458 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int test__checkterms_simple(struct list_head *terms) | ||
464 | { | ||
465 | struct parse_events__term *term; | ||
466 | |||
467 | /* config=10 */ | ||
468 | term = list_entry(terms->next, struct parse_events__term, list); | ||
469 | TEST_ASSERT_VAL("wrong type term", | ||
470 | term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG); | ||
471 | TEST_ASSERT_VAL("wrong type val", | ||
472 | term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); | ||
473 | TEST_ASSERT_VAL("wrong val", term->val.num == 10); | ||
474 | TEST_ASSERT_VAL("wrong config", !term->config); | ||
475 | |||
476 | /* config1 */ | ||
477 | term = list_entry(term->list.next, struct parse_events__term, list); | ||
478 | TEST_ASSERT_VAL("wrong type term", | ||
479 | term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1); | ||
480 | TEST_ASSERT_VAL("wrong type val", | ||
481 | term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); | ||
482 | TEST_ASSERT_VAL("wrong val", term->val.num == 1); | ||
483 | TEST_ASSERT_VAL("wrong config", !term->config); | ||
484 | |||
485 | /* config2=3 */ | ||
486 | term = list_entry(term->list.next, struct parse_events__term, list); | ||
487 | TEST_ASSERT_VAL("wrong type term", | ||
488 | term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2); | ||
489 | TEST_ASSERT_VAL("wrong type val", | ||
490 | term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); | ||
491 | TEST_ASSERT_VAL("wrong val", term->val.num == 3); | ||
492 | TEST_ASSERT_VAL("wrong config", !term->config); | ||
493 | |||
494 | /* umask=1*/ | ||
495 | term = list_entry(term->list.next, struct parse_events__term, list); | ||
496 | TEST_ASSERT_VAL("wrong type term", | ||
497 | term->type_term == PARSE_EVENTS__TERM_TYPE_USER); | ||
498 | TEST_ASSERT_VAL("wrong type val", | ||
499 | term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); | ||
500 | TEST_ASSERT_VAL("wrong val", term->val.num == 1); | ||
501 | TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask")); | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | static int test__group1(struct perf_evlist *evlist) | ||
507 | { | ||
508 | struct perf_evsel *evsel, *leader; | ||
509 | |||
510 | TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); | ||
511 | |||
512 | /* instructions:k */ | ||
513 | evsel = leader = perf_evlist__first(evlist); | ||
514 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
515 | TEST_ASSERT_VAL("wrong config", | ||
516 | PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); | ||
517 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
518 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
519 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
520 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
521 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
522 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
523 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
524 | |||
525 | /* cycles:upp */ | ||
526 | evsel = perf_evsel__next(evsel); | ||
527 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
528 | TEST_ASSERT_VAL("wrong config", | ||
529 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
530 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
531 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
532 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
533 | /* use of precise requires exclude_guest */ | ||
534 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
535 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
536 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); | ||
537 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static int test__group2(struct perf_evlist *evlist) | ||
543 | { | ||
544 | struct perf_evsel *evsel, *leader; | ||
545 | |||
546 | TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); | ||
547 | |||
548 | /* faults + :ku modifier */ | ||
549 | evsel = leader = perf_evlist__first(evlist); | ||
550 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); | ||
551 | TEST_ASSERT_VAL("wrong config", | ||
552 | PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); | ||
553 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
554 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
555 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
556 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
557 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
558 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
559 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
560 | |||
561 | /* cache-references + :u modifier */ | ||
562 | evsel = perf_evsel__next(evsel); | ||
563 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
564 | TEST_ASSERT_VAL("wrong config", | ||
565 | PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config); | ||
566 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
567 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
568 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
569 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
570 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
571 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
572 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
573 | |||
574 | /* cycles:k */ | ||
575 | evsel = perf_evsel__next(evsel); | ||
576 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
577 | TEST_ASSERT_VAL("wrong config", | ||
578 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
579 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
580 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
581 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
582 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
583 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
584 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
585 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | static int test__group3(struct perf_evlist *evlist __maybe_unused) | ||
591 | { | ||
592 | struct perf_evsel *evsel, *leader; | ||
593 | |||
594 | TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); | ||
595 | |||
596 | /* group1 syscalls:sys_enter_open:H */ | ||
597 | evsel = leader = perf_evlist__first(evlist); | ||
598 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); | ||
599 | TEST_ASSERT_VAL("wrong sample_type", | ||
600 | PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); | ||
601 | TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); | ||
602 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
603 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
604 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
605 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
606 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
607 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
608 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
609 | TEST_ASSERT_VAL("wrong group name", | ||
610 | !strcmp(leader->group_name, "group1")); | ||
611 | |||
612 | /* group1 cycles:kppp */ | ||
613 | evsel = perf_evsel__next(evsel); | ||
614 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
615 | TEST_ASSERT_VAL("wrong config", | ||
616 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
617 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
618 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
619 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
620 | /* use of precise requires exclude_guest */ | ||
621 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
622 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
623 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); | ||
624 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
625 | TEST_ASSERT_VAL("wrong group name", !evsel->group_name); | ||
626 | |||
627 | /* group2 cycles + G modifier */ | ||
628 | evsel = leader = perf_evsel__next(evsel); | ||
629 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
630 | TEST_ASSERT_VAL("wrong config", | ||
631 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
632 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
633 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
634 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
635 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
636 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
637 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
638 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
639 | TEST_ASSERT_VAL("wrong group name", | ||
640 | !strcmp(leader->group_name, "group2")); | ||
641 | |||
642 | /* group2 1:3 + G modifier */ | ||
643 | evsel = perf_evsel__next(evsel); | ||
644 | TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); | ||
645 | TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config); | ||
646 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
647 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
648 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
649 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
650 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
651 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
652 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
653 | |||
654 | /* instructions:u */ | ||
655 | evsel = perf_evsel__next(evsel); | ||
656 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
657 | TEST_ASSERT_VAL("wrong config", | ||
658 | PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); | ||
659 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
660 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
661 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
662 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
663 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
664 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
665 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static int test__group4(struct perf_evlist *evlist __maybe_unused) | ||
671 | { | ||
672 | struct perf_evsel *evsel, *leader; | ||
673 | |||
674 | TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); | ||
675 | |||
676 | /* cycles:u + p */ | ||
677 | evsel = leader = perf_evlist__first(evlist); | ||
678 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
679 | TEST_ASSERT_VAL("wrong config", | ||
680 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
681 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
682 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
683 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
684 | /* use of precise requires exclude_guest */ | ||
685 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
686 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
687 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); | ||
688 | TEST_ASSERT_VAL("wrong group name", !evsel->group_name); | ||
689 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
690 | |||
691 | /* instructions:kp + p */ | ||
692 | evsel = perf_evsel__next(evsel); | ||
693 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
694 | TEST_ASSERT_VAL("wrong config", | ||
695 | PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); | ||
696 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
697 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
698 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
699 | /* use of precise requires exclude_guest */ | ||
700 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
701 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
702 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); | ||
703 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static int test__group5(struct perf_evlist *evlist __maybe_unused) | ||
709 | { | ||
710 | struct perf_evsel *evsel, *leader; | ||
711 | |||
712 | TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); | ||
713 | |||
714 | /* cycles + G */ | ||
715 | evsel = leader = perf_evlist__first(evlist); | ||
716 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
717 | TEST_ASSERT_VAL("wrong config", | ||
718 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
719 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
720 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
721 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
722 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
723 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
724 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
725 | TEST_ASSERT_VAL("wrong group name", !evsel->group_name); | ||
726 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
727 | |||
728 | /* instructions + G */ | ||
729 | evsel = perf_evsel__next(evsel); | ||
730 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
731 | TEST_ASSERT_VAL("wrong config", | ||
732 | PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); | ||
733 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
734 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
735 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
736 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
737 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
738 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
739 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
740 | |||
741 | /* cycles:G */ | ||
742 | evsel = leader = perf_evsel__next(evsel); | ||
743 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
744 | TEST_ASSERT_VAL("wrong config", | ||
745 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
746 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
747 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
748 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
749 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
750 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
751 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
752 | TEST_ASSERT_VAL("wrong group name", !evsel->group_name); | ||
753 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
754 | |||
755 | /* instructions:G */ | ||
756 | evsel = perf_evsel__next(evsel); | ||
757 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
758 | TEST_ASSERT_VAL("wrong config", | ||
759 | PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); | ||
760 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
761 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
762 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
763 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
764 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
765 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
766 | TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); | ||
767 | |||
768 | /* cycles */ | ||
769 | evsel = perf_evsel__next(evsel); | ||
770 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); | ||
771 | TEST_ASSERT_VAL("wrong config", | ||
772 | PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); | ||
773 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
774 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
775 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
776 | TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); | ||
777 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
778 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
779 | TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | struct test__event_st { | ||
785 | const char *name; | ||
786 | __u32 type; | ||
787 | int (*check)(struct perf_evlist *evlist); | ||
788 | }; | ||
789 | |||
790 | static struct test__event_st test__events[] = { | ||
791 | [0] = { | ||
792 | .name = "syscalls:sys_enter_open", | ||
793 | .check = test__checkevent_tracepoint, | ||
794 | }, | ||
795 | [1] = { | ||
796 | .name = "syscalls:*", | ||
797 | .check = test__checkevent_tracepoint_multi, | ||
798 | }, | ||
799 | [2] = { | ||
800 | .name = "r1a", | ||
801 | .check = test__checkevent_raw, | ||
802 | }, | ||
803 | [3] = { | ||
804 | .name = "1:1", | ||
805 | .check = test__checkevent_numeric, | ||
806 | }, | ||
807 | [4] = { | ||
808 | .name = "instructions", | ||
809 | .check = test__checkevent_symbolic_name, | ||
810 | }, | ||
811 | [5] = { | ||
812 | .name = "cycles/period=100000,config2/", | ||
813 | .check = test__checkevent_symbolic_name_config, | ||
814 | }, | ||
815 | [6] = { | ||
816 | .name = "faults", | ||
817 | .check = test__checkevent_symbolic_alias, | ||
818 | }, | ||
819 | [7] = { | ||
820 | .name = "L1-dcache-load-miss", | ||
821 | .check = test__checkevent_genhw, | ||
822 | }, | ||
823 | [8] = { | ||
824 | .name = "mem:0", | ||
825 | .check = test__checkevent_breakpoint, | ||
826 | }, | ||
827 | [9] = { | ||
828 | .name = "mem:0:x", | ||
829 | .check = test__checkevent_breakpoint_x, | ||
830 | }, | ||
831 | [10] = { | ||
832 | .name = "mem:0:r", | ||
833 | .check = test__checkevent_breakpoint_r, | ||
834 | }, | ||
835 | [11] = { | ||
836 | .name = "mem:0:w", | ||
837 | .check = test__checkevent_breakpoint_w, | ||
838 | }, | ||
839 | [12] = { | ||
840 | .name = "syscalls:sys_enter_open:k", | ||
841 | .check = test__checkevent_tracepoint_modifier, | ||
842 | }, | ||
843 | [13] = { | ||
844 | .name = "syscalls:*:u", | ||
845 | .check = test__checkevent_tracepoint_multi_modifier, | ||
846 | }, | ||
847 | [14] = { | ||
848 | .name = "r1a:kp", | ||
849 | .check = test__checkevent_raw_modifier, | ||
850 | }, | ||
851 | [15] = { | ||
852 | .name = "1:1:hp", | ||
853 | .check = test__checkevent_numeric_modifier, | ||
854 | }, | ||
855 | [16] = { | ||
856 | .name = "instructions:h", | ||
857 | .check = test__checkevent_symbolic_name_modifier, | ||
858 | }, | ||
859 | [17] = { | ||
860 | .name = "faults:u", | ||
861 | .check = test__checkevent_symbolic_alias_modifier, | ||
862 | }, | ||
863 | [18] = { | ||
864 | .name = "L1-dcache-load-miss:kp", | ||
865 | .check = test__checkevent_genhw_modifier, | ||
866 | }, | ||
867 | [19] = { | ||
868 | .name = "mem:0:u", | ||
869 | .check = test__checkevent_breakpoint_modifier, | ||
870 | }, | ||
871 | [20] = { | ||
872 | .name = "mem:0:x:k", | ||
873 | .check = test__checkevent_breakpoint_x_modifier, | ||
874 | }, | ||
875 | [21] = { | ||
876 | .name = "mem:0:r:hp", | ||
877 | .check = test__checkevent_breakpoint_r_modifier, | ||
878 | }, | ||
879 | [22] = { | ||
880 | .name = "mem:0:w:up", | ||
881 | .check = test__checkevent_breakpoint_w_modifier, | ||
882 | }, | ||
883 | [23] = { | ||
884 | .name = "r1,syscalls:sys_enter_open:k,1:1:hp", | ||
885 | .check = test__checkevent_list, | ||
886 | }, | ||
887 | [24] = { | ||
888 | .name = "instructions:G", | ||
889 | .check = test__checkevent_exclude_host_modifier, | ||
890 | }, | ||
891 | [25] = { | ||
892 | .name = "instructions:H", | ||
893 | .check = test__checkevent_exclude_guest_modifier, | ||
894 | }, | ||
895 | [26] = { | ||
896 | .name = "mem:0:rw", | ||
897 | .check = test__checkevent_breakpoint_rw, | ||
898 | }, | ||
899 | [27] = { | ||
900 | .name = "mem:0:rw:kp", | ||
901 | .check = test__checkevent_breakpoint_rw_modifier, | ||
902 | }, | ||
903 | [28] = { | ||
904 | .name = "{instructions:k,cycles:upp}", | ||
905 | .check = test__group1, | ||
906 | }, | ||
907 | [29] = { | ||
908 | .name = "{faults:k,cache-references}:u,cycles:k", | ||
909 | .check = test__group2, | ||
910 | }, | ||
911 | [30] = { | ||
912 | .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u", | ||
913 | .check = test__group3, | ||
914 | }, | ||
915 | [31] = { | ||
916 | .name = "{cycles:u,instructions:kp}:p", | ||
917 | .check = test__group4, | ||
918 | }, | ||
919 | [32] = { | ||
920 | .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles", | ||
921 | .check = test__group5, | ||
922 | }, | ||
923 | }; | ||
924 | |||
925 | static struct test__event_st test__events_pmu[] = { | ||
926 | [0] = { | ||
927 | .name = "cpu/config=10,config1,config2=3,period=1000/u", | ||
928 | .check = test__checkevent_pmu, | ||
929 | }, | ||
930 | [1] = { | ||
931 | .name = "cpu/config=1,name=krava/u,cpu/config=2/u", | ||
932 | .check = test__checkevent_pmu_name, | ||
933 | }, | ||
934 | }; | ||
935 | |||
936 | struct test__term { | ||
937 | const char *str; | ||
938 | __u32 type; | ||
939 | int (*check)(struct list_head *terms); | ||
940 | }; | ||
941 | |||
942 | static struct test__term test__terms[] = { | ||
943 | [0] = { | ||
944 | .str = "config=10,config1,config2=3,umask=1", | ||
945 | .check = test__checkterms_simple, | ||
946 | }, | ||
947 | }; | ||
948 | |||
949 | static int test_event(struct test__event_st *e) | ||
950 | { | ||
951 | struct perf_evlist *evlist; | ||
952 | int ret; | ||
953 | |||
954 | evlist = perf_evlist__new(NULL, NULL); | ||
955 | if (evlist == NULL) | ||
956 | return -ENOMEM; | ||
957 | |||
958 | ret = parse_events(evlist, e->name, 0); | ||
959 | if (ret) { | ||
960 | pr_debug("failed to parse event '%s', err %d\n", | ||
961 | e->name, ret); | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | ret = e->check(evlist); | ||
966 | perf_evlist__delete(evlist); | ||
967 | |||
968 | return ret; | ||
969 | } | ||
970 | |||
971 | static int test_events(struct test__event_st *events, unsigned cnt) | ||
972 | { | ||
973 | int ret1, ret2 = 0; | ||
974 | unsigned i; | ||
975 | |||
976 | for (i = 0; i < cnt; i++) { | ||
977 | struct test__event_st *e = &events[i]; | ||
978 | |||
979 | pr_debug("running test %d '%s'\n", i, e->name); | ||
980 | ret1 = test_event(e); | ||
981 | if (ret1) | ||
982 | ret2 = ret1; | ||
983 | } | ||
984 | |||
985 | return ret2; | ||
986 | } | ||
987 | |||
988 | static int test_term(struct test__term *t) | ||
989 | { | ||
990 | struct list_head *terms; | ||
991 | int ret; | ||
992 | |||
993 | terms = malloc(sizeof(*terms)); | ||
994 | if (!terms) | ||
995 | return -ENOMEM; | ||
996 | |||
997 | INIT_LIST_HEAD(terms); | ||
998 | |||
999 | ret = parse_events_terms(terms, t->str); | ||
1000 | if (ret) { | ||
1001 | pr_debug("failed to parse terms '%s', err %d\n", | ||
1002 | t->str , ret); | ||
1003 | return ret; | ||
1004 | } | ||
1005 | |||
1006 | ret = t->check(terms); | ||
1007 | parse_events__free_terms(terms); | ||
1008 | |||
1009 | return ret; | ||
1010 | } | ||
1011 | |||
1012 | static int test_terms(struct test__term *terms, unsigned cnt) | ||
1013 | { | ||
1014 | int ret = 0; | ||
1015 | unsigned i; | ||
1016 | |||
1017 | for (i = 0; i < cnt; i++) { | ||
1018 | struct test__term *t = &terms[i]; | ||
1019 | |||
1020 | pr_debug("running test %d '%s'\n", i, t->str); | ||
1021 | ret = test_term(t); | ||
1022 | if (ret) | ||
1023 | break; | ||
1024 | } | ||
1025 | |||
1026 | return ret; | ||
1027 | } | ||
1028 | |||
1029 | static int test_pmu(void) | ||
1030 | { | ||
1031 | struct stat st; | ||
1032 | char path[PATH_MAX]; | ||
1033 | int ret; | ||
1034 | |||
1035 | snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/", | ||
1036 | sysfs_find_mountpoint()); | ||
1037 | |||
1038 | ret = stat(path, &st); | ||
1039 | if (ret) | ||
1040 | pr_debug("omitting PMU cpu tests\n"); | ||
1041 | return !ret; | ||
1042 | } | ||
1043 | |||
1044 | static int test_pmu_events(void) | ||
1045 | { | ||
1046 | struct stat st; | ||
1047 | char path[PATH_MAX]; | ||
1048 | struct dirent *ent; | ||
1049 | DIR *dir; | ||
1050 | int ret; | ||
1051 | |||
1052 | snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/", | ||
1053 | sysfs_find_mountpoint()); | ||
1054 | |||
1055 | ret = stat(path, &st); | ||
1056 | if (ret) { | ||
1057 | pr_debug("ommiting PMU cpu events tests\n"); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | dir = opendir(path); | ||
1062 | if (!dir) { | ||
1063 | pr_debug("can't open pmu event dir"); | ||
1064 | return -1; | ||
1065 | } | ||
1066 | |||
1067 | while (!ret && (ent = readdir(dir))) { | ||
1068 | #define MAX_NAME 100 | ||
1069 | struct test__event_st e; | ||
1070 | char name[MAX_NAME]; | ||
1071 | |||
1072 | if (!strcmp(ent->d_name, ".") || | ||
1073 | !strcmp(ent->d_name, "..")) | ||
1074 | continue; | ||
1075 | |||
1076 | snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name); | ||
1077 | |||
1078 | e.name = name; | ||
1079 | e.check = test__checkevent_pmu_events; | ||
1080 | |||
1081 | ret = test_event(&e); | ||
1082 | #undef MAX_NAME | ||
1083 | } | ||
1084 | |||
1085 | closedir(dir); | ||
1086 | return ret; | ||
1087 | } | ||
1088 | |||
1089 | int parse_events__test(void) | ||
1090 | { | ||
1091 | int ret1, ret2 = 0; | ||
1092 | |||
1093 | #define TEST_EVENTS(tests) \ | ||
1094 | do { \ | ||
1095 | ret1 = test_events(tests, ARRAY_SIZE(tests)); \ | ||
1096 | if (!ret2) \ | ||
1097 | ret2 = ret1; \ | ||
1098 | } while (0) | ||
1099 | |||
1100 | TEST_EVENTS(test__events); | ||
1101 | |||
1102 | if (test_pmu()) | ||
1103 | TEST_EVENTS(test__events_pmu); | ||
1104 | |||
1105 | if (test_pmu()) { | ||
1106 | int ret = test_pmu_events(); | ||
1107 | if (ret) | ||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1111 | ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms)); | ||
1112 | if (!ret2) | ||
1113 | ret2 = ret1; | ||
1114 | |||
1115 | return ret2; | ||
1116 | } | ||