18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <errno.h>
38c2ecf20Sopenharmony_ci#include <inttypes.h>
48c2ecf20Sopenharmony_ci/* For the CPU_* macros */
58c2ecf20Sopenharmony_ci#include <pthread.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <sys/types.h>
88c2ecf20Sopenharmony_ci#include <sys/stat.h>
98c2ecf20Sopenharmony_ci#include <fcntl.h>
108c2ecf20Sopenharmony_ci#include <api/fs/fs.h>
118c2ecf20Sopenharmony_ci#include <linux/err.h>
128c2ecf20Sopenharmony_ci#include <linux/string.h>
138c2ecf20Sopenharmony_ci#include <api/fs/tracing_path.h>
148c2ecf20Sopenharmony_ci#include "evsel.h"
158c2ecf20Sopenharmony_ci#include "tests.h"
168c2ecf20Sopenharmony_ci#include "thread_map.h"
178c2ecf20Sopenharmony_ci#include <perf/cpumap.h>
188c2ecf20Sopenharmony_ci#include <internal/cpumap.h>
198c2ecf20Sopenharmony_ci#include "debug.h"
208c2ecf20Sopenharmony_ci#include "stat.h"
218c2ecf20Sopenharmony_ci#include "util/counts.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciint test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	int err = -1, fd, cpu;
268c2ecf20Sopenharmony_ci	struct perf_cpu_map *cpus;
278c2ecf20Sopenharmony_ci	struct evsel *evsel;
288c2ecf20Sopenharmony_ci	unsigned int nr_openat_calls = 111, i;
298c2ecf20Sopenharmony_ci	cpu_set_t cpu_set;
308c2ecf20Sopenharmony_ci	struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
318c2ecf20Sopenharmony_ci	char sbuf[STRERR_BUFSIZE];
328c2ecf20Sopenharmony_ci	char errbuf[BUFSIZ];
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	if (threads == NULL) {
358c2ecf20Sopenharmony_ci		pr_debug("thread_map__new\n");
368c2ecf20Sopenharmony_ci		return -1;
378c2ecf20Sopenharmony_ci	}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	cpus = perf_cpu_map__new(NULL);
408c2ecf20Sopenharmony_ci	if (cpus == NULL) {
418c2ecf20Sopenharmony_ci		pr_debug("perf_cpu_map__new\n");
428c2ecf20Sopenharmony_ci		goto out_thread_map_delete;
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	CPU_ZERO(&cpu_set);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	evsel = evsel__newtp("syscalls", "sys_enter_openat");
488c2ecf20Sopenharmony_ci	if (IS_ERR(evsel)) {
498c2ecf20Sopenharmony_ci		tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
508c2ecf20Sopenharmony_ci		pr_debug("%s\n", errbuf);
518c2ecf20Sopenharmony_ci		goto out_cpu_map_delete;
528c2ecf20Sopenharmony_ci	}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (evsel__open(evsel, cpus, threads) < 0) {
558c2ecf20Sopenharmony_ci		pr_debug("failed to open counter: %s, "
568c2ecf20Sopenharmony_ci			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
578c2ecf20Sopenharmony_ci			 str_error_r(errno, sbuf, sizeof(sbuf)));
588c2ecf20Sopenharmony_ci		goto out_evsel_delete;
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	for (cpu = 0; cpu < cpus->nr; ++cpu) {
628c2ecf20Sopenharmony_ci		unsigned int ncalls = nr_openat_calls + cpu;
638c2ecf20Sopenharmony_ci		/*
648c2ecf20Sopenharmony_ci		 * XXX eventually lift this restriction in a way that
658c2ecf20Sopenharmony_ci		 * keeps perf building on older glibc installations
668c2ecf20Sopenharmony_ci		 * without CPU_ALLOC. 1024 cpus in 2010 still seems
678c2ecf20Sopenharmony_ci		 * a reasonable upper limit tho :-)
688c2ecf20Sopenharmony_ci		 */
698c2ecf20Sopenharmony_ci		if (cpus->map[cpu] >= CPU_SETSIZE) {
708c2ecf20Sopenharmony_ci			pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
718c2ecf20Sopenharmony_ci			continue;
728c2ecf20Sopenharmony_ci		}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci		CPU_SET(cpus->map[cpu], &cpu_set);
758c2ecf20Sopenharmony_ci		if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
768c2ecf20Sopenharmony_ci			pr_debug("sched_setaffinity() failed on CPU %d: %s ",
778c2ecf20Sopenharmony_ci				 cpus->map[cpu],
788c2ecf20Sopenharmony_ci				 str_error_r(errno, sbuf, sizeof(sbuf)));
798c2ecf20Sopenharmony_ci			goto out_close_fd;
808c2ecf20Sopenharmony_ci		}
818c2ecf20Sopenharmony_ci		for (i = 0; i < ncalls; ++i) {
828c2ecf20Sopenharmony_ci			fd = openat(0, "/etc/passwd", O_RDONLY);
838c2ecf20Sopenharmony_ci			close(fd);
848c2ecf20Sopenharmony_ci		}
858c2ecf20Sopenharmony_ci		CPU_CLR(cpus->map[cpu], &cpu_set);
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	/*
898c2ecf20Sopenharmony_ci	 * Here we need to explicitly preallocate the counts, as if
908c2ecf20Sopenharmony_ci	 * we use the auto allocation it will allocate just for 1 cpu,
918c2ecf20Sopenharmony_ci	 * as we start by cpu 0.
928c2ecf20Sopenharmony_ci	 */
938c2ecf20Sopenharmony_ci	if (evsel__alloc_counts(evsel, cpus->nr, 1) < 0) {
948c2ecf20Sopenharmony_ci		pr_debug("evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
958c2ecf20Sopenharmony_ci		goto out_close_fd;
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	err = 0;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	for (cpu = 0; cpu < cpus->nr; ++cpu) {
1018c2ecf20Sopenharmony_ci		unsigned int expected;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci		if (cpus->map[cpu] >= CPU_SETSIZE)
1048c2ecf20Sopenharmony_ci			continue;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci		if (evsel__read_on_cpu(evsel, cpu, 0) < 0) {
1078c2ecf20Sopenharmony_ci			pr_debug("evsel__read_on_cpu\n");
1088c2ecf20Sopenharmony_ci			err = -1;
1098c2ecf20Sopenharmony_ci			break;
1108c2ecf20Sopenharmony_ci		}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci		expected = nr_openat_calls + cpu;
1138c2ecf20Sopenharmony_ci		if (perf_counts(evsel->counts, cpu, 0)->val != expected) {
1148c2ecf20Sopenharmony_ci			pr_debug("evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
1158c2ecf20Sopenharmony_ci				 expected, cpus->map[cpu], perf_counts(evsel->counts, cpu, 0)->val);
1168c2ecf20Sopenharmony_ci			err = -1;
1178c2ecf20Sopenharmony_ci		}
1188c2ecf20Sopenharmony_ci	}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	evsel__free_counts(evsel);
1218c2ecf20Sopenharmony_ciout_close_fd:
1228c2ecf20Sopenharmony_ci	perf_evsel__close_fd(&evsel->core);
1238c2ecf20Sopenharmony_ciout_evsel_delete:
1248c2ecf20Sopenharmony_ci	evsel__delete(evsel);
1258c2ecf20Sopenharmony_ciout_cpu_map_delete:
1268c2ecf20Sopenharmony_ci	perf_cpu_map__put(cpus);
1278c2ecf20Sopenharmony_ciout_thread_map_delete:
1288c2ecf20Sopenharmony_ci	perf_thread_map__put(threads);
1298c2ecf20Sopenharmony_ci	return err;
1308c2ecf20Sopenharmony_ci}
131