18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Originally done by Vince Weaver <vincent.weaver@maine.edu> for 48c2ecf20Sopenharmony_ci * perf_event_tests (git://github.com/deater/perf_event_tests) 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/* 88c2ecf20Sopenharmony_ci * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select 98c2ecf20Sopenharmony_ci * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#define __SANE_USERSPACE_TYPES__ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <stdlib.h> 148c2ecf20Sopenharmony_ci#include <stdio.h> 158c2ecf20Sopenharmony_ci#include <unistd.h> 168c2ecf20Sopenharmony_ci#include <string.h> 178c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 188c2ecf20Sopenharmony_ci#include <time.h> 198c2ecf20Sopenharmony_ci#include <fcntl.h> 208c2ecf20Sopenharmony_ci#include <signal.h> 218c2ecf20Sopenharmony_ci#include <sys/mman.h> 228c2ecf20Sopenharmony_ci#include <linux/compiler.h> 238c2ecf20Sopenharmony_ci#include <linux/hw_breakpoint.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "tests.h" 268c2ecf20Sopenharmony_ci#include "debug.h" 278c2ecf20Sopenharmony_ci#include "event.h" 288c2ecf20Sopenharmony_ci#include "../perf-sys.h" 298c2ecf20Sopenharmony_ci#include "cloexec.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int overflows; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic noinline int test_function(void) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci return time(NULL); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void sig_handler(int signum __maybe_unused, 398c2ecf20Sopenharmony_ci siginfo_t *oh __maybe_unused, 408c2ecf20Sopenharmony_ci void *uc __maybe_unused) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci overflows++; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic long long bp_count(int fd) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci long long count; 488c2ecf20Sopenharmony_ci int ret; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ret = read(fd, &count, sizeof(long long)); 518c2ecf20Sopenharmony_ci if (ret != sizeof(long long)) { 528c2ecf20Sopenharmony_ci pr_debug("failed to read: %d\n", ret); 538c2ecf20Sopenharmony_ci return TEST_FAIL; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci return count; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define EXECUTIONS 10000 608c2ecf20Sopenharmony_ci#define THRESHOLD 100 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciint test__bp_signal_overflow(struct test *test __maybe_unused, int subtest __maybe_unused) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct perf_event_attr pe; 658c2ecf20Sopenharmony_ci struct sigaction sa; 668c2ecf20Sopenharmony_ci long long count; 678c2ecf20Sopenharmony_ci int fd, i, fails = 0; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* setup SIGIO signal handler */ 708c2ecf20Sopenharmony_ci memset(&sa, 0, sizeof(struct sigaction)); 718c2ecf20Sopenharmony_ci sa.sa_sigaction = (void *) sig_handler; 728c2ecf20Sopenharmony_ci sa.sa_flags = SA_SIGINFO; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (sigaction(SIGIO, &sa, NULL) < 0) { 758c2ecf20Sopenharmony_ci pr_debug("failed setting up signal handler\n"); 768c2ecf20Sopenharmony_ci return TEST_FAIL; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci memset(&pe, 0, sizeof(struct perf_event_attr)); 808c2ecf20Sopenharmony_ci pe.type = PERF_TYPE_BREAKPOINT; 818c2ecf20Sopenharmony_ci pe.size = sizeof(struct perf_event_attr); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci pe.config = 0; 848c2ecf20Sopenharmony_ci pe.bp_type = HW_BREAKPOINT_X; 858c2ecf20Sopenharmony_ci pe.bp_addr = (unsigned long) test_function; 868c2ecf20Sopenharmony_ci pe.bp_len = sizeof(long); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci pe.sample_period = THRESHOLD; 898c2ecf20Sopenharmony_ci pe.sample_type = PERF_SAMPLE_IP; 908c2ecf20Sopenharmony_ci pe.wakeup_events = 1; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci pe.disabled = 1; 938c2ecf20Sopenharmony_ci pe.exclude_kernel = 1; 948c2ecf20Sopenharmony_ci pe.exclude_hv = 1; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci fd = sys_perf_event_open(&pe, 0, -1, -1, 978c2ecf20Sopenharmony_ci perf_event_open_cloexec_flag()); 988c2ecf20Sopenharmony_ci if (fd < 0) { 998c2ecf20Sopenharmony_ci pr_debug("failed opening event %llx\n", pe.config); 1008c2ecf20Sopenharmony_ci return TEST_FAIL; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); 1048c2ecf20Sopenharmony_ci fcntl(fd, F_SETSIG, SIGIO); 1058c2ecf20Sopenharmony_ci fcntl(fd, F_SETOWN, getpid()); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_RESET, 0); 1088c2ecf20Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci for (i = 0; i < EXECUTIONS; i++) 1118c2ecf20Sopenharmony_ci test_function(); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci count = bp_count(fd); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci close(fd); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci pr_debug("count %lld, overflow %d\n", 1208c2ecf20Sopenharmony_ci count, overflows); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (count != EXECUTIONS) { 1238c2ecf20Sopenharmony_ci pr_debug("\tWrong number of executions %lld != %d\n", 1248c2ecf20Sopenharmony_ci count, EXECUTIONS); 1258c2ecf20Sopenharmony_ci fails++; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (overflows != EXECUTIONS / THRESHOLD) { 1298c2ecf20Sopenharmony_ci pr_debug("\tWrong number of overflows %d != %d\n", 1308c2ecf20Sopenharmony_ci overflows, EXECUTIONS / THRESHOLD); 1318c2ecf20Sopenharmony_ci fails++; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci return fails ? TEST_FAIL : TEST_OK; 1358c2ecf20Sopenharmony_ci} 136