1 // SPDX-License-Identifier: GPL-2.0 2 #include <stdarg.h> 3 #include <stdio.h> 4 #include <linux/perf_event.h> 5 #include <perf/cpumap.h> 6 #include <perf/threadmap.h> 7 #include <perf/evsel.h> 8 #include <internal/tests.h> 9 10 static int libperf_print(enum libperf_print_level level, 11 const char *fmt, va_list ap) 12 { 13 return vfprintf(stderr, fmt, ap); 14 } 15 16 static int test_stat_cpu(void) 17 { 18 struct perf_cpu_map *cpus; 19 struct perf_evsel *evsel; 20 struct perf_event_attr attr = { 21 .type = PERF_TYPE_SOFTWARE, 22 .config = PERF_COUNT_SW_CPU_CLOCK, 23 }; 24 int err, cpu, tmp; 25 26 cpus = perf_cpu_map__new(NULL); 27 __T("failed to create cpus", cpus); 28 29 evsel = perf_evsel__new(&attr); 30 __T("failed to create evsel", evsel); 31 32 err = perf_evsel__open(evsel, cpus, NULL); 33 __T("failed to open evsel", err == 0); 34 35 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { 36 struct perf_counts_values counts = { .val = 0 }; 37 38 perf_evsel__read(evsel, cpu, 0, &counts); 39 __T("failed to read value for evsel", counts.val != 0); 40 } 41 42 perf_evsel__close(evsel); 43 perf_evsel__delete(evsel); 44 45 perf_cpu_map__put(cpus); 46 return 0; 47 } 48 49 static int test_stat_thread(void) 50 { 51 struct perf_counts_values counts = { .val = 0 }; 52 struct perf_thread_map *threads; 53 struct perf_evsel *evsel; 54 struct perf_event_attr attr = { 55 .type = PERF_TYPE_SOFTWARE, 56 .config = PERF_COUNT_SW_TASK_CLOCK, 57 }; 58 int err; 59 60 threads = perf_thread_map__new_dummy(); 61 __T("failed to create threads", threads); 62 63 perf_thread_map__set_pid(threads, 0, 0); 64 65 evsel = perf_evsel__new(&attr); 66 __T("failed to create evsel", evsel); 67 68 err = perf_evsel__open(evsel, NULL, threads); 69 __T("failed to open evsel", err == 0); 70 71 perf_evsel__read(evsel, 0, 0, &counts); 72 __T("failed to read value for evsel", counts.val != 0); 73 74 perf_evsel__close(evsel); 75 perf_evsel__delete(evsel); 76 77 perf_thread_map__put(threads); 78 return 0; 79 } 80 81 static int test_stat_thread_enable(void) 82 { 83 struct perf_counts_values counts = { .val = 0 }; 84 struct perf_thread_map *threads; 85 struct perf_evsel *evsel; 86 struct perf_event_attr attr = { 87 .type = PERF_TYPE_SOFTWARE, 88 .config = PERF_COUNT_SW_TASK_CLOCK, 89 .disabled = 1, 90 }; 91 int err; 92 93 threads = perf_thread_map__new_dummy(); 94 __T("failed to create threads", threads); 95 96 perf_thread_map__set_pid(threads, 0, 0); 97 98 evsel = perf_evsel__new(&attr); 99 __T("failed to create evsel", evsel); 100 101 err = perf_evsel__open(evsel, NULL, threads); 102 __T("failed to open evsel", err == 0); 103 104 perf_evsel__read(evsel, 0, 0, &counts); 105 __T("failed to read value for evsel", counts.val == 0); 106 107 err = perf_evsel__enable(evsel); 108 __T("failed to enable evsel", err == 0); 109 110 perf_evsel__read(evsel, 0, 0, &counts); 111 __T("failed to read value for evsel", counts.val != 0); 112 113 err = perf_evsel__disable(evsel); 114 __T("failed to enable evsel", err == 0); 115 116 perf_evsel__close(evsel); 117 perf_evsel__delete(evsel); 118 119 perf_thread_map__put(threads); 120 return 0; 121 } 122 123 static int test_stat_user_read(int event) 124 { 125 struct perf_counts_values counts = { .val = 0 }; 126 struct perf_thread_map *threads; 127 struct perf_evsel *evsel; 128 struct perf_event_mmap_page *pc; 129 struct perf_event_attr attr = { 130 .type = PERF_TYPE_HARDWARE, 131 .config = event, 132 }; 133 int err, i; 134 135 threads = perf_thread_map__new_dummy(); 136 __T("failed to create threads", threads); 137 138 perf_thread_map__set_pid(threads, 0, 0); 139 140 evsel = perf_evsel__new(&attr); 141 __T("failed to create evsel", evsel); 142 143 err = perf_evsel__open(evsel, NULL, threads); 144 __T("failed to open evsel", err == 0); 145 146 err = perf_evsel__mmap(evsel, 0); 147 __T("failed to mmap evsel", err == 0); 148 149 pc = perf_evsel__mmap_base(evsel, 0, 0); 150 151 #if defined(__i386__) || defined(__x86_64__) 152 __T("userspace counter access not supported", pc->cap_user_rdpmc); 153 __T("userspace counter access not enabled", pc->index); 154 __T("userspace counter width not set", pc->pmc_width >= 32); 155 #endif 156 157 perf_evsel__read(evsel, 0, 0, &counts); 158 __T("failed to read value for evsel", counts.val != 0); 159 160 for (i = 0; i < 5; i++) { 161 volatile int count = 0x10000 << i; 162 __u64 start, end, last = 0; 163 164 __T_VERBOSE("\tloop = %u, ", count); 165 166 perf_evsel__read(evsel, 0, 0, &counts); 167 start = counts.val; 168 169 while (count--) ; 170 171 perf_evsel__read(evsel, 0, 0, &counts); 172 end = counts.val; 173 174 __T("invalid counter data", (end - start) > last); 175 last = end - start; 176 __T_VERBOSE("count = %llu\n", end - start); 177 } 178 179 perf_evsel__munmap(evsel); 180 perf_evsel__close(evsel); 181 perf_evsel__delete(evsel); 182 183 perf_thread_map__put(threads); 184 return 0; 185 } 186 187 int main(int argc, char **argv) 188 { 189 __T_START; 190 191 libperf_init(libperf_print); 192 193 test_stat_cpu(); 194 test_stat_thread(); 195 test_stat_thread_enable(); 196 test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS); 197 test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES); 198 199 __T_END; 200 return tests_failed == 0 ? 0 : -1; 201 } 202