1*3989bbf9SLeo Yan // SPDX-License-Identifier: GPL-2.0 2*3989bbf9SLeo Yan #include <errno.h> 3*3989bbf9SLeo Yan #include <inttypes.h> 4*3989bbf9SLeo Yan #include <limits.h> 5*3989bbf9SLeo Yan #include <stdbool.h> 6*3989bbf9SLeo Yan #include <stdio.h> 7*3989bbf9SLeo Yan #include <unistd.h> 8*3989bbf9SLeo Yan #include <linux/types.h> 9*3989bbf9SLeo Yan #include <sys/prctl.h> 10*3989bbf9SLeo Yan #include <perf/cpumap.h> 11*3989bbf9SLeo Yan #include <perf/evlist.h> 12*3989bbf9SLeo Yan #include <perf/mmap.h> 13*3989bbf9SLeo Yan 14*3989bbf9SLeo Yan #include "debug.h" 15*3989bbf9SLeo Yan #include "parse-events.h" 16*3989bbf9SLeo Yan #include "evlist.h" 17*3989bbf9SLeo Yan #include "evsel.h" 18*3989bbf9SLeo Yan #include "thread_map.h" 19*3989bbf9SLeo Yan #include "record.h" 20*3989bbf9SLeo Yan #include "tsc.h" 21*3989bbf9SLeo Yan #include "mmap.h" 22*3989bbf9SLeo Yan #include "tests.h" 23*3989bbf9SLeo Yan 24*3989bbf9SLeo Yan #define CHECK__(x) { \ 25*3989bbf9SLeo Yan while ((x) < 0) { \ 26*3989bbf9SLeo Yan pr_debug(#x " failed!\n"); \ 27*3989bbf9SLeo Yan goto out_err; \ 28*3989bbf9SLeo Yan } \ 29*3989bbf9SLeo Yan } 30*3989bbf9SLeo Yan 31*3989bbf9SLeo Yan #define CHECK_NOT_NULL__(x) { \ 32*3989bbf9SLeo Yan while ((x) == NULL) { \ 33*3989bbf9SLeo Yan pr_debug(#x " failed!\n"); \ 34*3989bbf9SLeo Yan goto out_err; \ 35*3989bbf9SLeo Yan } \ 36*3989bbf9SLeo Yan } 37*3989bbf9SLeo Yan 38*3989bbf9SLeo Yan /** 39*3989bbf9SLeo Yan * test__perf_time_to_tsc - test converting perf time to TSC. 40*3989bbf9SLeo Yan * 41*3989bbf9SLeo Yan * This function implements a test that checks that the conversion of perf time 42*3989bbf9SLeo Yan * to and from TSC is consistent with the order of events. If the test passes 43*3989bbf9SLeo Yan * %0 is returned, otherwise %-1 is returned. If TSC conversion is not 44*3989bbf9SLeo Yan * supported then then the test passes but " (not supported)" is printed. 45*3989bbf9SLeo Yan */ 46*3989bbf9SLeo Yan int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe_unused) 47*3989bbf9SLeo Yan { 48*3989bbf9SLeo Yan struct record_opts opts = { 49*3989bbf9SLeo Yan .mmap_pages = UINT_MAX, 50*3989bbf9SLeo Yan .user_freq = UINT_MAX, 51*3989bbf9SLeo Yan .user_interval = ULLONG_MAX, 52*3989bbf9SLeo Yan .target = { 53*3989bbf9SLeo Yan .uses_mmap = true, 54*3989bbf9SLeo Yan }, 55*3989bbf9SLeo Yan .sample_time = true, 56*3989bbf9SLeo Yan }; 57*3989bbf9SLeo Yan struct perf_thread_map *threads = NULL; 58*3989bbf9SLeo Yan struct perf_cpu_map *cpus = NULL; 59*3989bbf9SLeo Yan struct evlist *evlist = NULL; 60*3989bbf9SLeo Yan struct evsel *evsel = NULL; 61*3989bbf9SLeo Yan int err = -1, ret, i; 62*3989bbf9SLeo Yan const char *comm1, *comm2; 63*3989bbf9SLeo Yan struct perf_tsc_conversion tc; 64*3989bbf9SLeo Yan struct perf_event_mmap_page *pc; 65*3989bbf9SLeo Yan union perf_event *event; 66*3989bbf9SLeo Yan u64 test_tsc, comm1_tsc, comm2_tsc; 67*3989bbf9SLeo Yan u64 test_time, comm1_time = 0, comm2_time = 0; 68*3989bbf9SLeo Yan struct mmap *md; 69*3989bbf9SLeo Yan 70*3989bbf9SLeo Yan threads = thread_map__new(-1, getpid(), UINT_MAX); 71*3989bbf9SLeo Yan CHECK_NOT_NULL__(threads); 72*3989bbf9SLeo Yan 73*3989bbf9SLeo Yan cpus = perf_cpu_map__new(NULL); 74*3989bbf9SLeo Yan CHECK_NOT_NULL__(cpus); 75*3989bbf9SLeo Yan 76*3989bbf9SLeo Yan evlist = evlist__new(); 77*3989bbf9SLeo Yan CHECK_NOT_NULL__(evlist); 78*3989bbf9SLeo Yan 79*3989bbf9SLeo Yan perf_evlist__set_maps(&evlist->core, cpus, threads); 80*3989bbf9SLeo Yan 81*3989bbf9SLeo Yan CHECK__(parse_events(evlist, "cycles:u", NULL)); 82*3989bbf9SLeo Yan 83*3989bbf9SLeo Yan perf_evlist__config(evlist, &opts, NULL); 84*3989bbf9SLeo Yan 85*3989bbf9SLeo Yan evsel = evlist__first(evlist); 86*3989bbf9SLeo Yan 87*3989bbf9SLeo Yan evsel->core.attr.comm = 1; 88*3989bbf9SLeo Yan evsel->core.attr.disabled = 1; 89*3989bbf9SLeo Yan evsel->core.attr.enable_on_exec = 0; 90*3989bbf9SLeo Yan 91*3989bbf9SLeo Yan CHECK__(evlist__open(evlist)); 92*3989bbf9SLeo Yan 93*3989bbf9SLeo Yan CHECK__(evlist__mmap(evlist, UINT_MAX)); 94*3989bbf9SLeo Yan 95*3989bbf9SLeo Yan pc = evlist->mmap[0].core.base; 96*3989bbf9SLeo Yan ret = perf_read_tsc_conversion(pc, &tc); 97*3989bbf9SLeo Yan if (ret) { 98*3989bbf9SLeo Yan if (ret == -EOPNOTSUPP) { 99*3989bbf9SLeo Yan fprintf(stderr, " (not supported)"); 100*3989bbf9SLeo Yan return 0; 101*3989bbf9SLeo Yan } 102*3989bbf9SLeo Yan goto out_err; 103*3989bbf9SLeo Yan } 104*3989bbf9SLeo Yan 105*3989bbf9SLeo Yan evlist__enable(evlist); 106*3989bbf9SLeo Yan 107*3989bbf9SLeo Yan comm1 = "Test COMM 1"; 108*3989bbf9SLeo Yan CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0)); 109*3989bbf9SLeo Yan 110*3989bbf9SLeo Yan test_tsc = rdtsc(); 111*3989bbf9SLeo Yan 112*3989bbf9SLeo Yan comm2 = "Test COMM 2"; 113*3989bbf9SLeo Yan CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0)); 114*3989bbf9SLeo Yan 115*3989bbf9SLeo Yan evlist__disable(evlist); 116*3989bbf9SLeo Yan 117*3989bbf9SLeo Yan for (i = 0; i < evlist->core.nr_mmaps; i++) { 118*3989bbf9SLeo Yan md = &evlist->mmap[i]; 119*3989bbf9SLeo Yan if (perf_mmap__read_init(&md->core) < 0) 120*3989bbf9SLeo Yan continue; 121*3989bbf9SLeo Yan 122*3989bbf9SLeo Yan while ((event = perf_mmap__read_event(&md->core)) != NULL) { 123*3989bbf9SLeo Yan struct perf_sample sample; 124*3989bbf9SLeo Yan 125*3989bbf9SLeo Yan if (event->header.type != PERF_RECORD_COMM || 126*3989bbf9SLeo Yan (pid_t)event->comm.pid != getpid() || 127*3989bbf9SLeo Yan (pid_t)event->comm.tid != getpid()) 128*3989bbf9SLeo Yan goto next_event; 129*3989bbf9SLeo Yan 130*3989bbf9SLeo Yan if (strcmp(event->comm.comm, comm1) == 0) { 131*3989bbf9SLeo Yan CHECK__(evsel__parse_sample(evsel, event, &sample)); 132*3989bbf9SLeo Yan comm1_time = sample.time; 133*3989bbf9SLeo Yan } 134*3989bbf9SLeo Yan if (strcmp(event->comm.comm, comm2) == 0) { 135*3989bbf9SLeo Yan CHECK__(evsel__parse_sample(evsel, event, &sample)); 136*3989bbf9SLeo Yan comm2_time = sample.time; 137*3989bbf9SLeo Yan } 138*3989bbf9SLeo Yan next_event: 139*3989bbf9SLeo Yan perf_mmap__consume(&md->core); 140*3989bbf9SLeo Yan } 141*3989bbf9SLeo Yan perf_mmap__read_done(&md->core); 142*3989bbf9SLeo Yan } 143*3989bbf9SLeo Yan 144*3989bbf9SLeo Yan if (!comm1_time || !comm2_time) 145*3989bbf9SLeo Yan goto out_err; 146*3989bbf9SLeo Yan 147*3989bbf9SLeo Yan test_time = tsc_to_perf_time(test_tsc, &tc); 148*3989bbf9SLeo Yan comm1_tsc = perf_time_to_tsc(comm1_time, &tc); 149*3989bbf9SLeo Yan comm2_tsc = perf_time_to_tsc(comm2_time, &tc); 150*3989bbf9SLeo Yan 151*3989bbf9SLeo Yan pr_debug("1st event perf time %"PRIu64" tsc %"PRIu64"\n", 152*3989bbf9SLeo Yan comm1_time, comm1_tsc); 153*3989bbf9SLeo Yan pr_debug("rdtsc time %"PRIu64" tsc %"PRIu64"\n", 154*3989bbf9SLeo Yan test_time, test_tsc); 155*3989bbf9SLeo Yan pr_debug("2nd event perf time %"PRIu64" tsc %"PRIu64"\n", 156*3989bbf9SLeo Yan comm2_time, comm2_tsc); 157*3989bbf9SLeo Yan 158*3989bbf9SLeo Yan if (test_time <= comm1_time || 159*3989bbf9SLeo Yan test_time >= comm2_time) 160*3989bbf9SLeo Yan goto out_err; 161*3989bbf9SLeo Yan 162*3989bbf9SLeo Yan if (test_tsc <= comm1_tsc || 163*3989bbf9SLeo Yan test_tsc >= comm2_tsc) 164*3989bbf9SLeo Yan goto out_err; 165*3989bbf9SLeo Yan 166*3989bbf9SLeo Yan err = 0; 167*3989bbf9SLeo Yan 168*3989bbf9SLeo Yan out_err: 169*3989bbf9SLeo Yan evlist__delete(evlist); 170*3989bbf9SLeo Yan return err; 171*3989bbf9SLeo Yan } 172