1 // SPDX-License-Identifier: GPL-2.0 2 #include <stdarg.h> 3 #include <stdio.h> 4 #include <string.h> 5 #include <linux/perf_event.h> 6 #include <linux/kernel.h> 7 #include <perf/cpumap.h> 8 #include <perf/threadmap.h> 9 #include <perf/evsel.h> 10 #include <internal/evsel.h> 11 #include <internal/tests.h> 12 #include "tests.h" 13 14 static int libperf_print(enum libperf_print_level level, 15 const char *fmt, va_list ap) 16 { 17 return vfprintf(stderr, fmt, ap); 18 } 19 20 static int test_stat_cpu(void) 21 { 22 struct perf_cpu_map *cpus; 23 struct perf_evsel *evsel; 24 struct perf_event_attr attr = { 25 .type = PERF_TYPE_SOFTWARE, 26 .config = PERF_COUNT_SW_CPU_CLOCK, 27 }; 28 int err, idx; 29 30 cpus = perf_cpu_map__new(NULL); 31 __T("failed to create cpus", cpus); 32 33 evsel = perf_evsel__new(&attr); 34 __T("failed to create evsel", evsel); 35 36 err = perf_evsel__open(evsel, cpus, NULL); 37 __T("failed to open evsel", err == 0); 38 39 for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) { 40 struct perf_counts_values counts = { .val = 0 }; 41 42 perf_evsel__read(evsel, idx, 0, &counts); 43 __T("failed to read value for evsel", counts.val != 0); 44 } 45 46 perf_evsel__close(evsel); 47 perf_evsel__delete(evsel); 48 49 perf_cpu_map__put(cpus); 50 return 0; 51 } 52 53 static int test_stat_thread(void) 54 { 55 struct perf_counts_values counts = { .val = 0 }; 56 struct perf_thread_map *threads; 57 struct perf_evsel *evsel; 58 struct perf_event_attr attr = { 59 .type = PERF_TYPE_SOFTWARE, 60 .config = PERF_COUNT_SW_TASK_CLOCK, 61 }; 62 int err; 63 64 threads = perf_thread_map__new_dummy(); 65 __T("failed to create threads", threads); 66 67 perf_thread_map__set_pid(threads, 0, 0); 68 69 evsel = perf_evsel__new(&attr); 70 __T("failed to create evsel", evsel); 71 72 err = perf_evsel__open(evsel, NULL, threads); 73 __T("failed to open evsel", err == 0); 74 75 perf_evsel__read(evsel, 0, 0, &counts); 76 __T("failed to read value for evsel", counts.val != 0); 77 78 perf_evsel__close(evsel); 79 perf_evsel__delete(evsel); 80 81 perf_thread_map__put(threads); 82 return 0; 83 } 84 85 static int test_stat_thread_enable(void) 86 { 87 struct perf_counts_values counts = { .val = 0 }; 88 struct perf_thread_map *threads; 89 struct perf_evsel *evsel; 90 struct perf_event_attr attr = { 91 .type = PERF_TYPE_SOFTWARE, 92 .config = PERF_COUNT_SW_TASK_CLOCK, 93 .disabled = 1, 94 }; 95 int err; 96 97 threads = perf_thread_map__new_dummy(); 98 __T("failed to create threads", threads); 99 100 perf_thread_map__set_pid(threads, 0, 0); 101 102 evsel = perf_evsel__new(&attr); 103 __T("failed to create evsel", evsel); 104 105 err = perf_evsel__open(evsel, NULL, threads); 106 __T("failed to open evsel", err == 0); 107 108 perf_evsel__read(evsel, 0, 0, &counts); 109 __T("failed to read value for evsel", counts.val == 0); 110 111 err = perf_evsel__enable(evsel); 112 __T("failed to enable evsel", err == 0); 113 114 perf_evsel__read(evsel, 0, 0, &counts); 115 __T("failed to read value for evsel", counts.val != 0); 116 117 err = perf_evsel__disable(evsel); 118 __T("failed to enable evsel", err == 0); 119 120 perf_evsel__close(evsel); 121 perf_evsel__delete(evsel); 122 123 perf_thread_map__put(threads); 124 return 0; 125 } 126 127 static int test_stat_user_read(int event) 128 { 129 struct perf_counts_values counts = { .val = 0 }; 130 struct perf_thread_map *threads; 131 struct perf_evsel *evsel; 132 struct perf_event_mmap_page *pc; 133 struct perf_event_attr attr = { 134 .type = PERF_TYPE_HARDWARE, 135 .config = event, 136 #ifdef __aarch64__ 137 .config1 = 0x2, /* Request user access */ 138 #endif 139 }; 140 int err, i; 141 142 threads = perf_thread_map__new_dummy(); 143 __T("failed to create threads", threads); 144 145 perf_thread_map__set_pid(threads, 0, 0); 146 147 evsel = perf_evsel__new(&attr); 148 __T("failed to create evsel", evsel); 149 150 err = perf_evsel__open(evsel, NULL, threads); 151 __T("failed to open evsel", err == 0); 152 153 err = perf_evsel__mmap(evsel, 0); 154 __T("failed to mmap evsel", err == 0); 155 156 pc = perf_evsel__mmap_base(evsel, 0, 0); 157 __T("failed to get mmapped address", pc); 158 159 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) 160 __T("userspace counter access not supported", pc->cap_user_rdpmc); 161 __T("userspace counter access not enabled", pc->index); 162 __T("userspace counter width not set", pc->pmc_width >= 32); 163 #endif 164 165 perf_evsel__read(evsel, 0, 0, &counts); 166 __T("failed to read value for evsel", counts.val != 0); 167 168 for (i = 0; i < 5; i++) { 169 volatile int count = 0x10000 << i; 170 __u64 start, end, last = 0; 171 172 __T_VERBOSE("\tloop = %u, ", count); 173 174 perf_evsel__read(evsel, 0, 0, &counts); 175 start = counts.val; 176 177 while (count--) ; 178 179 perf_evsel__read(evsel, 0, 0, &counts); 180 end = counts.val; 181 182 __T("invalid counter data", (end - start) > last); 183 last = end - start; 184 __T_VERBOSE("count = %llu\n", end - start); 185 } 186 187 perf_evsel__munmap(evsel); 188 perf_evsel__close(evsel); 189 perf_evsel__delete(evsel); 190 191 perf_thread_map__put(threads); 192 return 0; 193 } 194 195 static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads) 196 { 197 struct perf_evsel *evsel; 198 struct perf_counts_values counts; 199 volatile int count = 0x100000; 200 int err; 201 202 evsel = perf_evsel__new(attr); 203 __T("failed to create evsel", evsel); 204 205 /* skip old kernels that don't support the format */ 206 err = perf_evsel__open(evsel, NULL, threads); 207 if (err < 0) 208 return 0; 209 210 while (count--) ; 211 212 memset(&counts, -1, sizeof(counts)); 213 perf_evsel__read(evsel, 0, 0, &counts); 214 215 __T("failed to read value", counts.val); 216 if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 217 __T("failed to read TOTAL_TIME_ENABLED", counts.ena); 218 if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 219 __T("failed to read TOTAL_TIME_RUNNING", counts.run); 220 if (attr->read_format & PERF_FORMAT_ID) 221 __T("failed to read ID", counts.id); 222 if (attr->read_format & PERF_FORMAT_LOST) 223 __T("failed to read LOST", counts.lost == 0); 224 225 perf_evsel__close(evsel); 226 perf_evsel__delete(evsel); 227 return 0; 228 } 229 230 static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads) 231 { 232 struct perf_evsel *leader, *member; 233 struct perf_counts_values counts; 234 volatile int count = 0x100000; 235 int err; 236 237 attr->read_format |= PERF_FORMAT_GROUP; 238 leader = perf_evsel__new(attr); 239 __T("failed to create leader", leader); 240 241 attr->read_format &= ~PERF_FORMAT_GROUP; 242 member = perf_evsel__new(attr); 243 __T("failed to create member", member); 244 245 member->leader = leader; 246 leader->nr_members = 2; 247 248 /* skip old kernels that don't support the format */ 249 err = perf_evsel__open(leader, NULL, threads); 250 if (err < 0) 251 return 0; 252 err = perf_evsel__open(member, NULL, threads); 253 if (err < 0) 254 return 0; 255 256 while (count--) ; 257 258 memset(&counts, -1, sizeof(counts)); 259 perf_evsel__read(leader, 0, 0, &counts); 260 261 __T("failed to read leader value", counts.val); 262 if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 263 __T("failed to read leader TOTAL_TIME_ENABLED", counts.ena); 264 if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 265 __T("failed to read leader TOTAL_TIME_RUNNING", counts.run); 266 if (attr->read_format & PERF_FORMAT_ID) 267 __T("failed to read leader ID", counts.id); 268 if (attr->read_format & PERF_FORMAT_LOST) 269 __T("failed to read leader LOST", counts.lost == 0); 270 271 memset(&counts, -1, sizeof(counts)); 272 perf_evsel__read(member, 0, 0, &counts); 273 274 __T("failed to read member value", counts.val); 275 if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 276 __T("failed to read member TOTAL_TIME_ENABLED", counts.ena); 277 if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 278 __T("failed to read member TOTAL_TIME_RUNNING", counts.run); 279 if (attr->read_format & PERF_FORMAT_ID) 280 __T("failed to read member ID", counts.id); 281 if (attr->read_format & PERF_FORMAT_LOST) 282 __T("failed to read member LOST", counts.lost == 0); 283 284 perf_evsel__close(member); 285 perf_evsel__close(leader); 286 perf_evsel__delete(member); 287 perf_evsel__delete(leader); 288 return 0; 289 } 290 291 static int test_stat_read_format(void) 292 { 293 struct perf_thread_map *threads; 294 struct perf_event_attr attr = { 295 .type = PERF_TYPE_SOFTWARE, 296 .config = PERF_COUNT_SW_TASK_CLOCK, 297 }; 298 int err, i; 299 300 #define FMT(_fmt) PERF_FORMAT_ ## _fmt 301 #define FMT_TIME (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING)) 302 303 uint64_t test_formats [] = { 304 0, 305 FMT_TIME, 306 FMT(ID), 307 FMT(LOST), 308 FMT_TIME | FMT(ID), 309 FMT_TIME | FMT(LOST), 310 FMT_TIME | FMT(ID) | FMT(LOST), 311 FMT(ID) | FMT(LOST), 312 }; 313 314 #undef FMT 315 #undef FMT_TIME 316 317 threads = perf_thread_map__new_dummy(); 318 __T("failed to create threads", threads); 319 320 perf_thread_map__set_pid(threads, 0, 0); 321 322 for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) { 323 attr.read_format = test_formats[i]; 324 __T_VERBOSE("testing single read with read_format: %lx\n", 325 (unsigned long)test_formats[i]); 326 327 err = test_stat_read_format_single(&attr, threads); 328 __T("failed to read single format", err == 0); 329 } 330 331 perf_thread_map__put(threads); 332 333 threads = perf_thread_map__new_array(2, NULL); 334 __T("failed to create threads", threads); 335 336 perf_thread_map__set_pid(threads, 0, 0); 337 perf_thread_map__set_pid(threads, 1, 0); 338 339 for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) { 340 attr.read_format = test_formats[i]; 341 __T_VERBOSE("testing group read with read_format: %lx\n", 342 (unsigned long)test_formats[i]); 343 344 err = test_stat_read_format_group(&attr, threads); 345 __T("failed to read group format", err == 0); 346 } 347 348 perf_thread_map__put(threads); 349 return 0; 350 } 351 352 int test_evsel(int argc, char **argv) 353 { 354 __T_START; 355 356 libperf_init(libperf_print); 357 358 test_stat_cpu(); 359 test_stat_thread(); 360 test_stat_thread_enable(); 361 test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS); 362 test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES); 363 test_stat_read_format(); 364 365 __T_END; 366 return tests_failed == 0 ? 0 : -1; 367 } 368