162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <errno.h> 362306a36Sopenharmony_ci#include <sched.h> 462306a36Sopenharmony_ci#include "util.h" // for sched_getcpu() 562306a36Sopenharmony_ci#include "../perf-sys.h" 662306a36Sopenharmony_ci#include "cloexec.h" 762306a36Sopenharmony_ci#include "event.h" 862306a36Sopenharmony_ci#include "asm/bug.h" 962306a36Sopenharmony_ci#include "debug.h" 1062306a36Sopenharmony_ci#include <unistd.h> 1162306a36Sopenharmony_ci#include <sys/syscall.h> 1262306a36Sopenharmony_ci#include <linux/string.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic unsigned long flag = PERF_FLAG_FD_CLOEXEC; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic int perf_flag_probe(void) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci /* use 'safest' configuration as used in evsel__fallback() */ 1962306a36Sopenharmony_ci struct perf_event_attr attr = { 2062306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 2162306a36Sopenharmony_ci .config = PERF_COUNT_SW_CPU_CLOCK, 2262306a36Sopenharmony_ci .exclude_kernel = 1, 2362306a36Sopenharmony_ci }; 2462306a36Sopenharmony_ci int fd; 2562306a36Sopenharmony_ci int err; 2662306a36Sopenharmony_ci int cpu; 2762306a36Sopenharmony_ci pid_t pid = -1; 2862306a36Sopenharmony_ci char sbuf[STRERR_BUFSIZE]; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci cpu = sched_getcpu(); 3162306a36Sopenharmony_ci if (cpu < 0) 3262306a36Sopenharmony_ci cpu = 0; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* 3562306a36Sopenharmony_ci * Using -1 for the pid is a workaround to avoid gratuitous jump label 3662306a36Sopenharmony_ci * changes. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci while (1) { 3962306a36Sopenharmony_ci /* check cloexec flag */ 4062306a36Sopenharmony_ci fd = sys_perf_event_open(&attr, pid, cpu, -1, 4162306a36Sopenharmony_ci PERF_FLAG_FD_CLOEXEC); 4262306a36Sopenharmony_ci if (fd < 0 && pid == -1 && errno == EACCES) { 4362306a36Sopenharmony_ci pid = 0; 4462306a36Sopenharmony_ci continue; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci err = errno; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (fd >= 0) { 5162306a36Sopenharmony_ci close(fd); 5262306a36Sopenharmony_ci return 1; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci WARN_ONCE(err != EINVAL && err != EBUSY && err != EACCES, 5662306a36Sopenharmony_ci "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 5762306a36Sopenharmony_ci err, str_error_r(err, sbuf, sizeof(sbuf))); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 6062306a36Sopenharmony_ci while (1) { 6162306a36Sopenharmony_ci fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); 6262306a36Sopenharmony_ci if (fd < 0 && pid == -1 && errno == EACCES) { 6362306a36Sopenharmony_ci pid = 0; 6462306a36Sopenharmony_ci continue; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci break; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci err = errno; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (fd >= 0) 7162306a36Sopenharmony_ci close(fd); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (WARN_ONCE(fd < 0 && err != EBUSY && err != EACCES, 7462306a36Sopenharmony_ci "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 7562306a36Sopenharmony_ci err, str_error_r(err, sbuf, sizeof(sbuf)))) 7662306a36Sopenharmony_ci return -1; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return 0; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciunsigned long perf_event_open_cloexec_flag(void) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci static bool probed; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (!probed) { 8662306a36Sopenharmony_ci if (perf_flag_probe() <= 0) 8762306a36Sopenharmony_ci flag = 0; 8862306a36Sopenharmony_ci probed = true; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return flag; 9262306a36Sopenharmony_ci} 93