18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Test backward bit in event attribute, read ring buffer from end to 48c2ecf20Sopenharmony_ci * beginning 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <evlist.h> 88c2ecf20Sopenharmony_ci#include <sys/prctl.h> 98c2ecf20Sopenharmony_ci#include "record.h" 108c2ecf20Sopenharmony_ci#include "tests.h" 118c2ecf20Sopenharmony_ci#include "debug.h" 128c2ecf20Sopenharmony_ci#include "parse-events.h" 138c2ecf20Sopenharmony_ci#include "util/mmap.h" 148c2ecf20Sopenharmony_ci#include <errno.h> 158c2ecf20Sopenharmony_ci#include <linux/string.h> 168c2ecf20Sopenharmony_ci#include <perf/mmap.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define NR_ITERS 111 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void testcase(void) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci int i; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci for (i = 0; i < NR_ITERS; i++) { 258c2ecf20Sopenharmony_ci char proc_name[15]; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci snprintf(proc_name, sizeof(proc_name), "p:%d\n", i); 288c2ecf20Sopenharmony_ci prctl(PR_SET_NAME, proc_name); 298c2ecf20Sopenharmony_ci } 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic int count_samples(struct evlist *evlist, int *sample_count, 338c2ecf20Sopenharmony_ci int *comm_count) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci int i; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci for (i = 0; i < evlist->core.nr_mmaps; i++) { 388c2ecf20Sopenharmony_ci struct mmap *map = &evlist->overwrite_mmap[i]; 398c2ecf20Sopenharmony_ci union perf_event *event; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci perf_mmap__read_init(&map->core); 428c2ecf20Sopenharmony_ci while ((event = perf_mmap__read_event(&map->core)) != NULL) { 438c2ecf20Sopenharmony_ci const u32 type = event->header.type; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci switch (type) { 468c2ecf20Sopenharmony_ci case PERF_RECORD_SAMPLE: 478c2ecf20Sopenharmony_ci (*sample_count)++; 488c2ecf20Sopenharmony_ci break; 498c2ecf20Sopenharmony_ci case PERF_RECORD_COMM: 508c2ecf20Sopenharmony_ci (*comm_count)++; 518c2ecf20Sopenharmony_ci break; 528c2ecf20Sopenharmony_ci default: 538c2ecf20Sopenharmony_ci pr_err("Unexpected record of type %d\n", type); 548c2ecf20Sopenharmony_ci return TEST_FAIL; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci perf_mmap__read_done(&map->core); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci return TEST_OK; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic int do_test(struct evlist *evlist, int mmap_pages, 638c2ecf20Sopenharmony_ci int *sample_count, int *comm_count) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci int err; 668c2ecf20Sopenharmony_ci char sbuf[STRERR_BUFSIZE]; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci err = evlist__mmap(evlist, mmap_pages); 698c2ecf20Sopenharmony_ci if (err < 0) { 708c2ecf20Sopenharmony_ci pr_debug("evlist__mmap: %s\n", 718c2ecf20Sopenharmony_ci str_error_r(errno, sbuf, sizeof(sbuf))); 728c2ecf20Sopenharmony_ci return TEST_FAIL; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci evlist__enable(evlist); 768c2ecf20Sopenharmony_ci testcase(); 778c2ecf20Sopenharmony_ci evlist__disable(evlist); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci err = count_samples(evlist, sample_count, comm_count); 808c2ecf20Sopenharmony_ci evlist__munmap(evlist); 818c2ecf20Sopenharmony_ci return err; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciint test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __maybe_unused) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; 888c2ecf20Sopenharmony_ci char pid[16], sbuf[STRERR_BUFSIZE]; 898c2ecf20Sopenharmony_ci struct evlist *evlist; 908c2ecf20Sopenharmony_ci struct evsel *evsel __maybe_unused; 918c2ecf20Sopenharmony_ci struct parse_events_error parse_error; 928c2ecf20Sopenharmony_ci struct record_opts opts = { 938c2ecf20Sopenharmony_ci .target = { 948c2ecf20Sopenharmony_ci .uid = UINT_MAX, 958c2ecf20Sopenharmony_ci .uses_mmap = true, 968c2ecf20Sopenharmony_ci }, 978c2ecf20Sopenharmony_ci .freq = 0, 988c2ecf20Sopenharmony_ci .mmap_pages = 256, 998c2ecf20Sopenharmony_ci .default_interval = 1, 1008c2ecf20Sopenharmony_ci }; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci snprintf(pid, sizeof(pid), "%d", getpid()); 1038c2ecf20Sopenharmony_ci pid[sizeof(pid) - 1] = '\0'; 1048c2ecf20Sopenharmony_ci opts.target.tid = opts.target.pid = pid; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci evlist = evlist__new(); 1078c2ecf20Sopenharmony_ci if (!evlist) { 1088c2ecf20Sopenharmony_ci pr_debug("Not enough memory to create evlist\n"); 1098c2ecf20Sopenharmony_ci return TEST_FAIL; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci err = perf_evlist__create_maps(evlist, &opts.target); 1138c2ecf20Sopenharmony_ci if (err < 0) { 1148c2ecf20Sopenharmony_ci pr_debug("Not enough memory to create thread/cpu maps\n"); 1158c2ecf20Sopenharmony_ci goto out_delete_evlist; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci bzero(&parse_error, sizeof(parse_error)); 1198c2ecf20Sopenharmony_ci /* 1208c2ecf20Sopenharmony_ci * Set backward bit, ring buffer should be writing from end. Record 1218c2ecf20Sopenharmony_ci * it in aux evlist 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_ci err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error); 1248c2ecf20Sopenharmony_ci if (err) { 1258c2ecf20Sopenharmony_ci pr_debug("Failed to parse tracepoint event, try use root\n"); 1268c2ecf20Sopenharmony_ci ret = TEST_SKIP; 1278c2ecf20Sopenharmony_ci goto out_delete_evlist; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci perf_evlist__config(evlist, &opts, NULL); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci err = evlist__open(evlist); 1338c2ecf20Sopenharmony_ci if (err < 0) { 1348c2ecf20Sopenharmony_ci pr_debug("perf_evlist__open: %s\n", 1358c2ecf20Sopenharmony_ci str_error_r(errno, sbuf, sizeof(sbuf))); 1368c2ecf20Sopenharmony_ci goto out_delete_evlist; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci ret = TEST_FAIL; 1408c2ecf20Sopenharmony_ci err = do_test(evlist, opts.mmap_pages, &sample_count, 1418c2ecf20Sopenharmony_ci &comm_count); 1428c2ecf20Sopenharmony_ci if (err != TEST_OK) 1438c2ecf20Sopenharmony_ci goto out_delete_evlist; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) { 1468c2ecf20Sopenharmony_ci pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n", 1478c2ecf20Sopenharmony_ci sample_count, comm_count); 1488c2ecf20Sopenharmony_ci goto out_delete_evlist; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci evlist__close(evlist); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci err = evlist__open(evlist); 1548c2ecf20Sopenharmony_ci if (err < 0) { 1558c2ecf20Sopenharmony_ci pr_debug("perf_evlist__open: %s\n", 1568c2ecf20Sopenharmony_ci str_error_r(errno, sbuf, sizeof(sbuf))); 1578c2ecf20Sopenharmony_ci goto out_delete_evlist; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci err = do_test(evlist, 1, &sample_count, &comm_count); 1618c2ecf20Sopenharmony_ci if (err != TEST_OK) 1628c2ecf20Sopenharmony_ci goto out_delete_evlist; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci ret = TEST_OK; 1658c2ecf20Sopenharmony_ciout_delete_evlist: 1668c2ecf20Sopenharmony_ci evlist__delete(evlist); 1678c2ecf20Sopenharmony_ci return ret; 1688c2ecf20Sopenharmony_ci} 169