1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2a43783aeSArnaldo Carvalho de Melo #include <errno.h>
3f6edb53cSAdrian Hunter #include <sched.h>
4fb71c86cSArnaldo Carvalho de Melo #include "util.h" // for sched_getcpu()
591854f9aSArnaldo Carvalho de Melo #include "../perf-sys.h"
657480d2cSYann Droneaud #include "cloexec.h"
78520a98dSArnaldo Carvalho de Melo #include "event.h"
857480d2cSYann Droneaud #include "asm/bug.h"
96e81c74cSMasami Hiramatsu #include "debug.h"
10c7007e98SArnaldo Carvalho de Melo #include <unistd.h>
11c7007e98SArnaldo Carvalho de Melo #include <sys/syscall.h>
128520a98dSArnaldo Carvalho de Melo #include <linux/string.h>
1357480d2cSYann Droneaud
1457480d2cSYann Droneaud static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
1557480d2cSYann Droneaud
perf_flag_probe(void)1657480d2cSYann Droneaud static int perf_flag_probe(void)
1757480d2cSYann Droneaud {
18ae430892SArnaldo Carvalho de Melo /* use 'safest' configuration as used in evsel__fallback() */
1957480d2cSYann Droneaud struct perf_event_attr attr = {
20038fa0b9SJiri Olsa .type = PERF_TYPE_SOFTWARE,
2157480d2cSYann Droneaud .config = PERF_COUNT_SW_CPU_CLOCK,
22a5b0153cSAdrian Hunter .exclude_kernel = 1,
2357480d2cSYann Droneaud };
2457480d2cSYann Droneaud int fd;
2557480d2cSYann Droneaud int err;
26f6edb53cSAdrian Hunter int cpu;
27f6edb53cSAdrian Hunter pid_t pid = -1;
286e81c74cSMasami Hiramatsu char sbuf[STRERR_BUFSIZE];
2957480d2cSYann Droneaud
30f6edb53cSAdrian Hunter cpu = sched_getcpu();
31f6edb53cSAdrian Hunter if (cpu < 0)
32f6edb53cSAdrian Hunter cpu = 0;
33f6edb53cSAdrian Hunter
3448536c91SAdrian Hunter /*
3548536c91SAdrian Hunter * Using -1 for the pid is a workaround to avoid gratuitous jump label
3648536c91SAdrian Hunter * changes.
3748536c91SAdrian Hunter */
38f6edb53cSAdrian Hunter while (1) {
3957480d2cSYann Droneaud /* check cloexec flag */
40f6edb53cSAdrian Hunter fd = sys_perf_event_open(&attr, pid, cpu, -1,
4157480d2cSYann Droneaud PERF_FLAG_FD_CLOEXEC);
42f6edb53cSAdrian Hunter if (fd < 0 && pid == -1 && errno == EACCES) {
43f6edb53cSAdrian Hunter pid = 0;
44f6edb53cSAdrian Hunter continue;
45f6edb53cSAdrian Hunter }
46f6edb53cSAdrian Hunter break;
47f6edb53cSAdrian Hunter }
4857480d2cSYann Droneaud err = errno;
4957480d2cSYann Droneaud
5057480d2cSYann Droneaud if (fd >= 0) {
5157480d2cSYann Droneaud close(fd);
5257480d2cSYann Droneaud return 1;
5357480d2cSYann Droneaud }
5457480d2cSYann Droneaud
55*c1034eb0SAlexey Budankov WARN_ONCE(err != EINVAL && err != EBUSY && err != EACCES,
5657480d2cSYann Droneaud "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
57c8b5f2c9SArnaldo Carvalho de Melo err, str_error_r(err, sbuf, sizeof(sbuf)));
5857480d2cSYann Droneaud
5957480d2cSYann Droneaud /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
6048536c91SAdrian Hunter while (1) {
61f6edb53cSAdrian Hunter fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
6248536c91SAdrian Hunter if (fd < 0 && pid == -1 && errno == EACCES) {
6348536c91SAdrian Hunter pid = 0;
6448536c91SAdrian Hunter continue;
6548536c91SAdrian Hunter }
6648536c91SAdrian Hunter break;
6748536c91SAdrian Hunter }
6857480d2cSYann Droneaud err = errno;
6957480d2cSYann Droneaud
7048536c91SAdrian Hunter if (fd >= 0)
7148536c91SAdrian Hunter close(fd);
7248536c91SAdrian Hunter
73*c1034eb0SAlexey Budankov if (WARN_ONCE(fd < 0 && err != EBUSY && err != EACCES,
7457480d2cSYann Droneaud "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
75c8b5f2c9SArnaldo Carvalho de Melo err, str_error_r(err, sbuf, sizeof(sbuf))))
7657480d2cSYann Droneaud return -1;
7757480d2cSYann Droneaud
7857480d2cSYann Droneaud return 0;
7957480d2cSYann Droneaud }
8057480d2cSYann Droneaud
perf_event_open_cloexec_flag(void)8157480d2cSYann Droneaud unsigned long perf_event_open_cloexec_flag(void)
8257480d2cSYann Droneaud {
8357480d2cSYann Droneaud static bool probed;
8457480d2cSYann Droneaud
8557480d2cSYann Droneaud if (!probed) {
8657480d2cSYann Droneaud if (perf_flag_probe() <= 0)
8757480d2cSYann Droneaud flag = 0;
8857480d2cSYann Droneaud probed = true;
8957480d2cSYann Droneaud }
9057480d2cSYann Droneaud
9157480d2cSYann Droneaud return flag;
9257480d2cSYann Droneaud }
93