13989bbf9SLeo Yan // SPDX-License-Identifier: GPL-2.0 23989bbf9SLeo Yan #include <errno.h> 33989bbf9SLeo Yan #include <inttypes.h> 43989bbf9SLeo Yan #include <limits.h> 53989bbf9SLeo Yan #include <stdbool.h> 63989bbf9SLeo Yan #include <stdio.h> 73989bbf9SLeo Yan #include <unistd.h> 83989bbf9SLeo Yan #include <linux/types.h> 93989bbf9SLeo Yan #include <sys/prctl.h> 103989bbf9SLeo Yan #include <perf/cpumap.h> 113989bbf9SLeo Yan #include <perf/evlist.h> 123989bbf9SLeo Yan #include <perf/mmap.h> 133989bbf9SLeo Yan 143989bbf9SLeo Yan #include "debug.h" 153989bbf9SLeo Yan #include "parse-events.h" 163989bbf9SLeo Yan #include "evlist.h" 173989bbf9SLeo Yan #include "evsel.h" 183989bbf9SLeo Yan #include "thread_map.h" 193989bbf9SLeo Yan #include "record.h" 203989bbf9SLeo Yan #include "tsc.h" 213989bbf9SLeo Yan #include "mmap.h" 223989bbf9SLeo Yan #include "tests.h" 233989bbf9SLeo Yan 24e74dd9cbSIan Rogers /* 25e74dd9cbSIan Rogers * Except x86_64/i386 and Arm64, other archs don't support TSC in perf. Just 26e74dd9cbSIan Rogers * enable the test for x86_64/i386 and Arm64 archs. 27e74dd9cbSIan Rogers */ 28e74dd9cbSIan Rogers #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) 29e74dd9cbSIan Rogers #define TSC_IS_SUPPORTED 1 30e74dd9cbSIan Rogers #else 31e74dd9cbSIan Rogers #define TSC_IS_SUPPORTED 0 32e74dd9cbSIan Rogers #endif 33e74dd9cbSIan Rogers 343989bbf9SLeo Yan #define CHECK__(x) { \ 353989bbf9SLeo Yan while ((x) < 0) { \ 363989bbf9SLeo Yan pr_debug(#x " failed!\n"); \ 373989bbf9SLeo Yan goto out_err; \ 383989bbf9SLeo Yan } \ 393989bbf9SLeo Yan } 403989bbf9SLeo Yan 413989bbf9SLeo Yan #define CHECK_NOT_NULL__(x) { \ 423989bbf9SLeo Yan while ((x) == NULL) { \ 433989bbf9SLeo Yan pr_debug(#x " failed!\n"); \ 443989bbf9SLeo Yan goto out_err; \ 453989bbf9SLeo Yan } \ 463989bbf9SLeo Yan } 473989bbf9SLeo Yan 48290fa68bSChengdong Li static int test__tsc_is_supported(struct test_suite *test __maybe_unused, 49290fa68bSChengdong Li int subtest __maybe_unused) 50290fa68bSChengdong Li { 51290fa68bSChengdong Li if (!TSC_IS_SUPPORTED) { 52290fa68bSChengdong Li pr_debug("Test not supported on this architecture\n"); 53290fa68bSChengdong Li return TEST_SKIP; 54290fa68bSChengdong Li } 55290fa68bSChengdong Li 56290fa68bSChengdong Li return TEST_OK; 57290fa68bSChengdong Li } 58290fa68bSChengdong Li 593989bbf9SLeo Yan /** 603989bbf9SLeo Yan * test__perf_time_to_tsc - test converting perf time to TSC. 613989bbf9SLeo Yan * 623989bbf9SLeo Yan * This function implements a test that checks that the conversion of perf time 633989bbf9SLeo Yan * to and from TSC is consistent with the order of events. If the test passes 643989bbf9SLeo Yan * %0 is returned, otherwise %-1 is returned. If TSC conversion is not 653989bbf9SLeo Yan * supported then then the test passes but " (not supported)" is printed. 663989bbf9SLeo Yan */ 6733f44bfdSIan Rogers static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 683989bbf9SLeo Yan { 693989bbf9SLeo Yan struct record_opts opts = { 703989bbf9SLeo Yan .mmap_pages = UINT_MAX, 713989bbf9SLeo Yan .user_freq = UINT_MAX, 723989bbf9SLeo Yan .user_interval = ULLONG_MAX, 733989bbf9SLeo Yan .target = { 743989bbf9SLeo Yan .uses_mmap = true, 753989bbf9SLeo Yan }, 763989bbf9SLeo Yan .sample_time = true, 773989bbf9SLeo Yan }; 783989bbf9SLeo Yan struct perf_thread_map *threads = NULL; 793989bbf9SLeo Yan struct perf_cpu_map *cpus = NULL; 803989bbf9SLeo Yan struct evlist *evlist = NULL; 813989bbf9SLeo Yan struct evsel *evsel = NULL; 82290fa68bSChengdong Li int err = TEST_FAIL, ret, i; 833989bbf9SLeo Yan const char *comm1, *comm2; 843989bbf9SLeo Yan struct perf_tsc_conversion tc; 853989bbf9SLeo Yan struct perf_event_mmap_page *pc; 863989bbf9SLeo Yan union perf_event *event; 873989bbf9SLeo Yan u64 test_tsc, comm1_tsc, comm2_tsc; 883989bbf9SLeo Yan u64 test_time, comm1_time = 0, comm2_time = 0; 893989bbf9SLeo Yan struct mmap *md; 903989bbf9SLeo Yan 91e74dd9cbSIan Rogers 923989bbf9SLeo Yan threads = thread_map__new(-1, getpid(), UINT_MAX); 933989bbf9SLeo Yan CHECK_NOT_NULL__(threads); 943989bbf9SLeo Yan 953989bbf9SLeo Yan cpus = perf_cpu_map__new(NULL); 963989bbf9SLeo Yan CHECK_NOT_NULL__(cpus); 973989bbf9SLeo Yan 983989bbf9SLeo Yan evlist = evlist__new(); 993989bbf9SLeo Yan CHECK_NOT_NULL__(evlist); 1003989bbf9SLeo Yan 1013989bbf9SLeo Yan perf_evlist__set_maps(&evlist->core, cpus, threads); 1023989bbf9SLeo Yan 1033989bbf9SLeo Yan CHECK__(parse_events(evlist, "cycles:u", NULL)); 1043989bbf9SLeo Yan 10578e1bc25SArnaldo Carvalho de Melo evlist__config(evlist, &opts, NULL); 1063989bbf9SLeo Yan 107*deb44a62SAdrian Hunter /* For hybrid "cycles:u", it creates two events */ 108*deb44a62SAdrian Hunter evlist__for_each_entry(evlist, evsel) { 109d9da6f70SJin Yao evsel->core.attr.comm = 1; 110d9da6f70SJin Yao evsel->core.attr.disabled = 1; 111d9da6f70SJin Yao evsel->core.attr.enable_on_exec = 0; 112d9da6f70SJin Yao } 113d9da6f70SJin Yao 114498c7a54SAdrian Hunter ret = evlist__open(evlist); 115498c7a54SAdrian Hunter if (ret < 0) { 116498c7a54SAdrian Hunter if (ret == -ENOENT) 1175bb017d4SThomas Richter err = TEST_SKIP; 118498c7a54SAdrian Hunter else 119498c7a54SAdrian Hunter pr_debug("evlist__open() failed\n"); 1205bb017d4SThomas Richter goto out_err; 1215bb017d4SThomas Richter } 1223989bbf9SLeo Yan 1233989bbf9SLeo Yan CHECK__(evlist__mmap(evlist, UINT_MAX)); 1243989bbf9SLeo Yan 1253989bbf9SLeo Yan pc = evlist->mmap[0].core.base; 1263989bbf9SLeo Yan ret = perf_read_tsc_conversion(pc, &tc); 1273989bbf9SLeo Yan if (ret) { 1283989bbf9SLeo Yan if (ret == -EOPNOTSUPP) { 129290fa68bSChengdong Li pr_debug("perf_read_tsc_conversion is not supported in current kernel\n"); 130290fa68bSChengdong Li err = TEST_SKIP; 1313989bbf9SLeo Yan } 1323989bbf9SLeo Yan goto out_err; 1333989bbf9SLeo Yan } 1343989bbf9SLeo Yan 1353989bbf9SLeo Yan evlist__enable(evlist); 1363989bbf9SLeo Yan 1373989bbf9SLeo Yan comm1 = "Test COMM 1"; 1383989bbf9SLeo Yan CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0)); 1393989bbf9SLeo Yan 1403989bbf9SLeo Yan test_tsc = rdtsc(); 1413989bbf9SLeo Yan 1423989bbf9SLeo Yan comm2 = "Test COMM 2"; 1433989bbf9SLeo Yan CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0)); 1443989bbf9SLeo Yan 1453989bbf9SLeo Yan evlist__disable(evlist); 1463989bbf9SLeo Yan 1473989bbf9SLeo Yan for (i = 0; i < evlist->core.nr_mmaps; i++) { 1483989bbf9SLeo Yan md = &evlist->mmap[i]; 1493989bbf9SLeo Yan if (perf_mmap__read_init(&md->core) < 0) 1503989bbf9SLeo Yan continue; 1513989bbf9SLeo Yan 1523989bbf9SLeo Yan while ((event = perf_mmap__read_event(&md->core)) != NULL) { 1533989bbf9SLeo Yan struct perf_sample sample; 1543989bbf9SLeo Yan 1553989bbf9SLeo Yan if (event->header.type != PERF_RECORD_COMM || 1563989bbf9SLeo Yan (pid_t)event->comm.pid != getpid() || 1573989bbf9SLeo Yan (pid_t)event->comm.tid != getpid()) 1583989bbf9SLeo Yan goto next_event; 1593989bbf9SLeo Yan 1603989bbf9SLeo Yan if (strcmp(event->comm.comm, comm1) == 0) { 161*deb44a62SAdrian Hunter CHECK_NOT_NULL__(evsel = evlist__event2evsel(evlist, event)); 1623989bbf9SLeo Yan CHECK__(evsel__parse_sample(evsel, event, &sample)); 1633989bbf9SLeo Yan comm1_time = sample.time; 1643989bbf9SLeo Yan } 1653989bbf9SLeo Yan if (strcmp(event->comm.comm, comm2) == 0) { 166*deb44a62SAdrian Hunter CHECK_NOT_NULL__(evsel = evlist__event2evsel(evlist, event)); 1673989bbf9SLeo Yan CHECK__(evsel__parse_sample(evsel, event, &sample)); 1683989bbf9SLeo Yan comm2_time = sample.time; 1693989bbf9SLeo Yan } 1703989bbf9SLeo Yan next_event: 1713989bbf9SLeo Yan perf_mmap__consume(&md->core); 1723989bbf9SLeo Yan } 1733989bbf9SLeo Yan perf_mmap__read_done(&md->core); 1743989bbf9SLeo Yan } 1753989bbf9SLeo Yan 1763989bbf9SLeo Yan if (!comm1_time || !comm2_time) 1773989bbf9SLeo Yan goto out_err; 1783989bbf9SLeo Yan 1793989bbf9SLeo Yan test_time = tsc_to_perf_time(test_tsc, &tc); 1803989bbf9SLeo Yan comm1_tsc = perf_time_to_tsc(comm1_time, &tc); 1813989bbf9SLeo Yan comm2_tsc = perf_time_to_tsc(comm2_time, &tc); 1823989bbf9SLeo Yan 1833989bbf9SLeo Yan pr_debug("1st event perf time %"PRIu64" tsc %"PRIu64"\n", 1843989bbf9SLeo Yan comm1_time, comm1_tsc); 1853989bbf9SLeo Yan pr_debug("rdtsc time %"PRIu64" tsc %"PRIu64"\n", 1863989bbf9SLeo Yan test_time, test_tsc); 1873989bbf9SLeo Yan pr_debug("2nd event perf time %"PRIu64" tsc %"PRIu64"\n", 1883989bbf9SLeo Yan comm2_time, comm2_tsc); 1893989bbf9SLeo Yan 1903989bbf9SLeo Yan if (test_time <= comm1_time || 1913989bbf9SLeo Yan test_time >= comm2_time) 1923989bbf9SLeo Yan goto out_err; 1933989bbf9SLeo Yan 1943989bbf9SLeo Yan if (test_tsc <= comm1_tsc || 1953989bbf9SLeo Yan test_tsc >= comm2_tsc) 1963989bbf9SLeo Yan goto out_err; 1973989bbf9SLeo Yan 198290fa68bSChengdong Li err = TEST_OK; 1993989bbf9SLeo Yan 2003989bbf9SLeo Yan out_err: 2013989bbf9SLeo Yan evlist__delete(evlist); 202846580c2SNamhyung Kim perf_cpu_map__put(cpus); 203846580c2SNamhyung Kim perf_thread_map__put(threads); 2043989bbf9SLeo Yan return err; 2053989bbf9SLeo Yan } 206248dd9b5SLeo Yan 207290fa68bSChengdong Li static struct test_case time_to_tsc_tests[] = { 208290fa68bSChengdong Li TEST_CASE_REASON("TSC support", tsc_is_supported, 209290fa68bSChengdong Li "This architecture does not support"), 210290fa68bSChengdong Li TEST_CASE_REASON("Perf time to TSC", perf_time_to_tsc, 211290fa68bSChengdong Li "perf_read_tsc_conversion is not supported"), 212290fa68bSChengdong Li { .name = NULL, } 213290fa68bSChengdong Li }; 214290fa68bSChengdong Li 215290fa68bSChengdong Li struct test_suite suite__perf_time_to_tsc = { 216290fa68bSChengdong Li .desc = "Convert perf time to TSC", 217290fa68bSChengdong Li .test_cases = time_to_tsc_tests, 218290fa68bSChengdong Li }; 219