1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2b31d660dSJiri Olsa #include <linux/compiler.h>
38520a98dSArnaldo Carvalho de Melo #include <linux/string.h>
4a43783aeSArnaldo Carvalho de Melo #include <errno.h>
5fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
6b31d660dSJiri Olsa #include <string.h>
74208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
89c3516d1SJiri Olsa #include <perf/cpumap.h>
9b31d660dSJiri Olsa #include "tests.h"
10b31d660dSJiri Olsa #include "evlist.h"
11b31d660dSJiri Olsa #include "evsel.h"
12b31d660dSJiri Olsa #include "debug.h"
13f2a39fe8SArnaldo Carvalho de Melo #include "parse-events.h"
14b31d660dSJiri Olsa #include "thread_map.h"
15b31d660dSJiri Olsa #include "target.h"
16b31d660dSJiri Olsa
attach__enable_on_exec(struct evlist * evlist)1763503dbaSJiri Olsa static int attach__enable_on_exec(struct evlist *evlist)
18b31d660dSJiri Olsa {
19515dbe48SJiri Olsa struct evsel *evsel = evlist__last(evlist);
20b31d660dSJiri Olsa struct target target = {
21b31d660dSJiri Olsa .uid = UINT_MAX,
22b31d660dSJiri Olsa };
23b31d660dSJiri Olsa const char *argv[] = { "true", NULL, };
24b31d660dSJiri Olsa char sbuf[STRERR_BUFSIZE];
25b31d660dSJiri Olsa int err;
26b31d660dSJiri Olsa
27b31d660dSJiri Olsa pr_debug("attaching to spawned child, enable on exec\n");
28b31d660dSJiri Olsa
297748bb71SArnaldo Carvalho de Melo err = evlist__create_maps(evlist, &target);
30b31d660dSJiri Olsa if (err < 0) {
31b31d660dSJiri Olsa pr_debug("Not enough memory to create thread/cpu maps\n");
32b31d660dSJiri Olsa return err;
33b31d660dSJiri Olsa }
34b31d660dSJiri Olsa
357b392ef0SArnaldo Carvalho de Melo err = evlist__prepare_workload(evlist, &target, argv, false, NULL);
36b31d660dSJiri Olsa if (err < 0) {
37b31d660dSJiri Olsa pr_debug("Couldn't run the workload!\n");
38b31d660dSJiri Olsa return err;
39b31d660dSJiri Olsa }
40b31d660dSJiri Olsa
411fc632ceSJiri Olsa evsel->core.attr.enable_on_exec = 1;
42b31d660dSJiri Olsa
43474ddc4cSJiri Olsa err = evlist__open(evlist);
44b31d660dSJiri Olsa if (err < 0) {
45b31d660dSJiri Olsa pr_debug("perf_evlist__open: %s\n",
46c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, sbuf, sizeof(sbuf)));
47b31d660dSJiri Olsa return err;
48b31d660dSJiri Olsa }
49b31d660dSJiri Olsa
507b392ef0SArnaldo Carvalho de Melo return evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
51b31d660dSJiri Olsa }
52b31d660dSJiri Olsa
detach__enable_on_exec(struct evlist * evlist)5363503dbaSJiri Olsa static int detach__enable_on_exec(struct evlist *evlist)
54b31d660dSJiri Olsa {
55b31d660dSJiri Olsa waitpid(evlist->workload.pid, NULL, 0);
56b31d660dSJiri Olsa return 0;
57b31d660dSJiri Olsa }
58b31d660dSJiri Olsa
attach__current_disabled(struct evlist * evlist)5963503dbaSJiri Olsa static int attach__current_disabled(struct evlist *evlist)
60b31d660dSJiri Olsa {
61515dbe48SJiri Olsa struct evsel *evsel = evlist__last(evlist);
629749b90eSJiri Olsa struct perf_thread_map *threads;
63b31d660dSJiri Olsa int err;
64b31d660dSJiri Olsa
65b31d660dSJiri Olsa pr_debug("attaching to current thread as disabled\n");
66b31d660dSJiri Olsa
67b31d660dSJiri Olsa threads = thread_map__new(-1, getpid(), UINT_MAX);
68b31d660dSJiri Olsa if (threads == NULL) {
69b31d660dSJiri Olsa pr_debug("thread_map__new\n");
70b31d660dSJiri Olsa return -1;
71b31d660dSJiri Olsa }
72b31d660dSJiri Olsa
731fc632ceSJiri Olsa evsel->core.attr.disabled = 1;
74b31d660dSJiri Olsa
75aa8c406bSArnaldo Carvalho de Melo err = evsel__open_per_thread(evsel, threads);
76b31d660dSJiri Olsa if (err) {
77b31d660dSJiri Olsa pr_debug("Failed to open event cpu-clock:u\n");
78b31d660dSJiri Olsa return err;
79b31d660dSJiri Olsa }
80b31d660dSJiri Olsa
817836e52eSJiri Olsa perf_thread_map__put(threads);
82ec7f24efSJiri Olsa return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
83b31d660dSJiri Olsa }
84b31d660dSJiri Olsa
attach__current_enabled(struct evlist * evlist)8563503dbaSJiri Olsa static int attach__current_enabled(struct evlist *evlist)
86b31d660dSJiri Olsa {
87515dbe48SJiri Olsa struct evsel *evsel = evlist__last(evlist);
889749b90eSJiri Olsa struct perf_thread_map *threads;
89b31d660dSJiri Olsa int err;
90b31d660dSJiri Olsa
91b31d660dSJiri Olsa pr_debug("attaching to current thread as enabled\n");
92b31d660dSJiri Olsa
93b31d660dSJiri Olsa threads = thread_map__new(-1, getpid(), UINT_MAX);
94b31d660dSJiri Olsa if (threads == NULL) {
95b31d660dSJiri Olsa pr_debug("failed to call thread_map__new\n");
96b31d660dSJiri Olsa return -1;
97b31d660dSJiri Olsa }
98b31d660dSJiri Olsa
99aa8c406bSArnaldo Carvalho de Melo err = evsel__open_per_thread(evsel, threads);
100b31d660dSJiri Olsa
1017836e52eSJiri Olsa perf_thread_map__put(threads);
102b31d660dSJiri Olsa return err == 0 ? TEST_OK : TEST_FAIL;
103b31d660dSJiri Olsa }
104b31d660dSJiri Olsa
detach__disable(struct evlist * evlist)10563503dbaSJiri Olsa static int detach__disable(struct evlist *evlist)
106b31d660dSJiri Olsa {
107515dbe48SJiri Olsa struct evsel *evsel = evlist__last(evlist);
108b31d660dSJiri Olsa
109ec7f24efSJiri Olsa return evsel__enable(evsel);
110b31d660dSJiri Olsa }
111b31d660dSJiri Olsa
attach__cpu_disabled(struct evlist * evlist)11263503dbaSJiri Olsa static int attach__cpu_disabled(struct evlist *evlist)
113b31d660dSJiri Olsa {
114515dbe48SJiri Olsa struct evsel *evsel = evlist__last(evlist);
115f854839bSJiri Olsa struct perf_cpu_map *cpus;
116b31d660dSJiri Olsa int err;
117b31d660dSJiri Olsa
118b31d660dSJiri Olsa pr_debug("attaching to CPU 0 as enabled\n");
119b31d660dSJiri Olsa
1209c3516d1SJiri Olsa cpus = perf_cpu_map__new("0");
121b31d660dSJiri Olsa if (cpus == NULL) {
1229c3516d1SJiri Olsa pr_debug("failed to call perf_cpu_map__new\n");
123b31d660dSJiri Olsa return -1;
124b31d660dSJiri Olsa }
125b31d660dSJiri Olsa
1261fc632ceSJiri Olsa evsel->core.attr.disabled = 1;
127b31d660dSJiri Olsa
128aa8c406bSArnaldo Carvalho de Melo err = evsel__open_per_cpu(evsel, cpus, -1);
129b31d660dSJiri Olsa if (err) {
130b31d660dSJiri Olsa if (err == -EACCES)
131b31d660dSJiri Olsa return TEST_SKIP;
132b31d660dSJiri Olsa
133b31d660dSJiri Olsa pr_debug("Failed to open event cpu-clock:u\n");
134b31d660dSJiri Olsa return err;
135b31d660dSJiri Olsa }
136b31d660dSJiri Olsa
13738f01d8dSJiri Olsa perf_cpu_map__put(cpus);
138ec7f24efSJiri Olsa return evsel__enable(evsel);
139b31d660dSJiri Olsa }
140b31d660dSJiri Olsa
attach__cpu_enabled(struct evlist * evlist)14163503dbaSJiri Olsa static int attach__cpu_enabled(struct evlist *evlist)
142b31d660dSJiri Olsa {
143515dbe48SJiri Olsa struct evsel *evsel = evlist__last(evlist);
144f854839bSJiri Olsa struct perf_cpu_map *cpus;
145b31d660dSJiri Olsa int err;
146b31d660dSJiri Olsa
147b31d660dSJiri Olsa pr_debug("attaching to CPU 0 as enabled\n");
148b31d660dSJiri Olsa
1499c3516d1SJiri Olsa cpus = perf_cpu_map__new("0");
150b31d660dSJiri Olsa if (cpus == NULL) {
1519c3516d1SJiri Olsa pr_debug("failed to call perf_cpu_map__new\n");
152b31d660dSJiri Olsa return -1;
153b31d660dSJiri Olsa }
154b31d660dSJiri Olsa
155aa8c406bSArnaldo Carvalho de Melo err = evsel__open_per_cpu(evsel, cpus, -1);
156b31d660dSJiri Olsa if (err == -EACCES)
157b31d660dSJiri Olsa return TEST_SKIP;
158b31d660dSJiri Olsa
15938f01d8dSJiri Olsa perf_cpu_map__put(cpus);
160b31d660dSJiri Olsa return err ? TEST_FAIL : TEST_OK;
161b31d660dSJiri Olsa }
162b31d660dSJiri Olsa
test_times(int (attach)(struct evlist *),int (detach)(struct evlist *))16363503dbaSJiri Olsa static int test_times(int (attach)(struct evlist *),
16463503dbaSJiri Olsa int (detach)(struct evlist *))
165b31d660dSJiri Olsa {
166b31d660dSJiri Olsa struct perf_counts_values count;
16763503dbaSJiri Olsa struct evlist *evlist = NULL;
16832dcd021SJiri Olsa struct evsel *evsel;
169b31d660dSJiri Olsa int err = -1, i;
170b31d660dSJiri Olsa
1710f98b11cSJiri Olsa evlist = evlist__new();
172b31d660dSJiri Olsa if (!evlist) {
173b31d660dSJiri Olsa pr_debug("failed to create event list\n");
174b31d660dSJiri Olsa goto out_err;
175b31d660dSJiri Olsa }
176b31d660dSJiri Olsa
177*806731a9SAdrian Hunter err = parse_event(evlist, "cpu-clock:u");
178b31d660dSJiri Olsa if (err) {
179b31d660dSJiri Olsa pr_debug("failed to parse event cpu-clock:u\n");
180b31d660dSJiri Olsa goto out_err;
181b31d660dSJiri Olsa }
182b31d660dSJiri Olsa
183515dbe48SJiri Olsa evsel = evlist__last(evlist);
1841fc632ceSJiri Olsa evsel->core.attr.read_format |=
185b31d660dSJiri Olsa PERF_FORMAT_TOTAL_TIME_ENABLED |
186b31d660dSJiri Olsa PERF_FORMAT_TOTAL_TIME_RUNNING;
187b31d660dSJiri Olsa
188b31d660dSJiri Olsa err = attach(evlist);
189b31d660dSJiri Olsa if (err == TEST_SKIP) {
190b31d660dSJiri Olsa pr_debug(" SKIP : not enough rights\n");
191b31d660dSJiri Olsa return err;
192b31d660dSJiri Olsa }
193b31d660dSJiri Olsa
194b31d660dSJiri Olsa TEST_ASSERT_VAL("failed to attach", !err);
195b31d660dSJiri Olsa
196b31d660dSJiri Olsa for (i = 0; i < 100000000; i++) { }
197b31d660dSJiri Olsa
198b31d660dSJiri Olsa TEST_ASSERT_VAL("failed to detach", !detach(evlist));
199b31d660dSJiri Olsa
2005c30af92SJiri Olsa perf_evsel__read(&evsel->core, 0, 0, &count);
201b31d660dSJiri Olsa
202b31d660dSJiri Olsa err = !(count.ena == count.run);
203b31d660dSJiri Olsa
204b31d660dSJiri Olsa pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n",
205b31d660dSJiri Olsa !err ? "OK " : "FAILED",
206b31d660dSJiri Olsa count.ena, count.run);
207b31d660dSJiri Olsa
208b31d660dSJiri Olsa out_err:
209c12995a5SJiri Olsa evlist__delete(evlist);
210b31d660dSJiri Olsa return !err ? TEST_OK : TEST_FAIL;
211b31d660dSJiri Olsa }
212b31d660dSJiri Olsa
213b31d660dSJiri Olsa /*
214b31d660dSJiri Olsa * This test creates software event 'cpu-clock'
215b31d660dSJiri Olsa * attaches it in several ways (explained below)
216b31d660dSJiri Olsa * and checks that enabled and running times
217b31d660dSJiri Olsa * match.
218b31d660dSJiri Olsa */
test__event_times(struct test_suite * test __maybe_unused,int subtest __maybe_unused)21933f44bfdSIan Rogers static int test__event_times(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
220b31d660dSJiri Olsa {
221b31d660dSJiri Olsa int err, ret = 0;
222b31d660dSJiri Olsa
223b31d660dSJiri Olsa #define _T(attach, detach) \
224b31d660dSJiri Olsa err = test_times(attach, detach); \
225b31d660dSJiri Olsa if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
226b31d660dSJiri Olsa ret = err;
227b31d660dSJiri Olsa
228b31d660dSJiri Olsa /* attach on newly spawned process after exec */
229b31d660dSJiri Olsa _T(attach__enable_on_exec, detach__enable_on_exec)
230b31d660dSJiri Olsa /* attach on current process as enabled */
231b31d660dSJiri Olsa _T(attach__current_enabled, detach__disable)
232b31d660dSJiri Olsa /* attach on current process as disabled */
233b31d660dSJiri Olsa _T(attach__current_disabled, detach__disable)
234b31d660dSJiri Olsa /* attach on cpu as disabled */
235b31d660dSJiri Olsa _T(attach__cpu_disabled, detach__disable)
236b31d660dSJiri Olsa /* attach on cpu as enabled */
237b31d660dSJiri Olsa _T(attach__cpu_enabled, detach__disable)
238b31d660dSJiri Olsa
239b31d660dSJiri Olsa #undef _T
240b31d660dSJiri Olsa return ret;
241b31d660dSJiri Olsa }
242d68f0365SIan Rogers
243d68f0365SIan Rogers DEFINE_SUITE("Event times", event_times);
244