1241675Suqs// SPDX-License-Identifier: GPL-2.0 2241675Suqs#include <stdarg.h> 3241675Suqs#include <stdio.h> 4241675Suqs#include <string.h> 5241675Suqs#include <linux/perf_event.h> 6241675Suqs#include <linux/kernel.h> 7241675Suqs#include <perf/cpumap.h> 8241675Suqs#include <perf/threadmap.h> 9241675Suqs#include <perf/evsel.h> 10241675Suqs#include <internal/evsel.h> 11241675Suqs#include <internal/tests.h> 12241675Suqs#include "tests.h" 13241675Suqs 14241675Suqsstatic int libperf_print(enum libperf_print_level level, 15241675Suqs const char *fmt, va_list ap) 16241675Suqs{ 17241675Suqs return vfprintf(stderr, fmt, ap); 18241675Suqs} 19241675Suqs 20241675Suqsstatic int test_stat_cpu(void) 21241675Suqs{ 22241675Suqs struct perf_cpu_map *cpus; 23241675Suqs struct perf_evsel *evsel; 24241675Suqs struct perf_event_attr attr = { 25241675Suqs .type = PERF_TYPE_SOFTWARE, 26241675Suqs .config = PERF_COUNT_SW_CPU_CLOCK, 27241675Suqs }; 28241675Suqs int err, idx; 29241675Suqs 30241675Suqs cpus = perf_cpu_map__new_online_cpus(); 31241675Suqs __T("failed to create cpus", cpus); 32241675Suqs 33241675Suqs evsel = perf_evsel__new(&attr); 34241675Suqs __T("failed to create evsel", evsel); 35241675Suqs 36241675Suqs err = perf_evsel__open(evsel, cpus, NULL); 37241675Suqs __T("failed to open evsel", err == 0); 38241675Suqs 39241675Suqs for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) { 40241675Suqs struct perf_counts_values counts = { .val = 0 }; 41241675Suqs 42241675Suqs perf_evsel__read(evsel, idx, 0, &counts); 43241675Suqs __T("failed to read value for evsel", counts.val != 0); 44241675Suqs } 45241675Suqs 46241675Suqs perf_evsel__close(evsel); 47241675Suqs perf_evsel__delete(evsel); 48241675Suqs 49241675Suqs perf_cpu_map__put(cpus); 50241675Suqs return 0; 51241675Suqs} 52241675Suqs 53241675Suqsstatic int test_stat_thread(void) 54241675Suqs{ 55241675Suqs struct perf_counts_values counts = { .val = 0 }; 56241675Suqs struct perf_thread_map *threads; 57241675Suqs struct perf_evsel *evsel; 58241675Suqs struct perf_event_attr attr = { 59241675Suqs .type = PERF_TYPE_SOFTWARE, 60241675Suqs .config = PERF_COUNT_SW_TASK_CLOCK, 61241675Suqs }; 62241675Suqs int err; 63241675Suqs 64241675Suqs threads = perf_thread_map__new_dummy(); 65241675Suqs __T("failed to create threads", threads); 66241675Suqs 67241675Suqs perf_thread_map__set_pid(threads, 0, 0); 68241675Suqs 69241675Suqs evsel = perf_evsel__new(&attr); 70241675Suqs __T("failed to create evsel", evsel); 71241675Suqs 72241675Suqs err = perf_evsel__open(evsel, NULL, threads); 73241675Suqs __T("failed to open evsel", err == 0); 74241675Suqs 75241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 76241675Suqs __T("failed to read value for evsel", counts.val != 0); 77241675Suqs 78241675Suqs perf_evsel__close(evsel); 79241675Suqs perf_evsel__delete(evsel); 80241675Suqs 81241675Suqs perf_thread_map__put(threads); 82241675Suqs return 0; 83241675Suqs} 84241675Suqs 85241675Suqsstatic int test_stat_thread_enable(void) 86241675Suqs{ 87241675Suqs struct perf_counts_values counts = { .val = 0 }; 88241675Suqs struct perf_thread_map *threads; 89241675Suqs struct perf_evsel *evsel; 90241675Suqs struct perf_event_attr attr = { 91241675Suqs .type = PERF_TYPE_SOFTWARE, 92241675Suqs .config = PERF_COUNT_SW_TASK_CLOCK, 93241675Suqs .disabled = 1, 94241675Suqs }; 95241675Suqs int err; 96241675Suqs 97241675Suqs threads = perf_thread_map__new_dummy(); 98241675Suqs __T("failed to create threads", threads); 99241675Suqs 100241675Suqs perf_thread_map__set_pid(threads, 0, 0); 101241675Suqs 102241675Suqs evsel = perf_evsel__new(&attr); 103241675Suqs __T("failed to create evsel", evsel); 104241675Suqs 105241675Suqs err = perf_evsel__open(evsel, NULL, threads); 106241675Suqs __T("failed to open evsel", err == 0); 107241675Suqs 108241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 109241675Suqs __T("failed to read value for evsel", counts.val == 0); 110241675Suqs 111241675Suqs err = perf_evsel__enable(evsel); 112241675Suqs __T("failed to enable evsel", err == 0); 113241675Suqs 114241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 115241675Suqs __T("failed to read value for evsel", counts.val != 0); 116241675Suqs 117241675Suqs err = perf_evsel__disable(evsel); 118241675Suqs __T("failed to enable evsel", err == 0); 119241675Suqs 120241675Suqs perf_evsel__close(evsel); 121241675Suqs perf_evsel__delete(evsel); 122241675Suqs 123241675Suqs perf_thread_map__put(threads); 124241675Suqs return 0; 125241675Suqs} 126241675Suqs 127241675Suqsstatic int test_stat_user_read(int event) 128241675Suqs{ 129241675Suqs struct perf_counts_values counts = { .val = 0 }; 130241675Suqs struct perf_thread_map *threads; 131241675Suqs struct perf_evsel *evsel; 132241675Suqs struct perf_event_mmap_page *pc; 133241675Suqs struct perf_event_attr attr = { 134241675Suqs .type = PERF_TYPE_HARDWARE, 135241675Suqs .config = event, 136241675Suqs#ifdef __aarch64__ 137241675Suqs .config1 = 0x2, /* Request user access */ 138241675Suqs#endif 139241675Suqs }; 140241675Suqs int err, i; 141241675Suqs 142241675Suqs threads = perf_thread_map__new_dummy(); 143241675Suqs __T("failed to create threads", threads); 144241675Suqs 145241675Suqs perf_thread_map__set_pid(threads, 0, 0); 146241675Suqs 147241675Suqs evsel = perf_evsel__new(&attr); 148241675Suqs __T("failed to create evsel", evsel); 149241675Suqs 150241675Suqs err = perf_evsel__open(evsel, NULL, threads); 151241675Suqs __T("failed to open evsel", err == 0); 152241675Suqs 153241675Suqs err = perf_evsel__mmap(evsel, 0); 154241675Suqs __T("failed to mmap evsel", err == 0); 155241675Suqs 156241675Suqs pc = perf_evsel__mmap_base(evsel, 0, 0); 157241675Suqs __T("failed to get mmapped address", pc); 158241675Suqs 159241675Suqs#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) 160241675Suqs __T("userspace counter access not supported", pc->cap_user_rdpmc); 161241675Suqs __T("userspace counter access not enabled", pc->index); 162241675Suqs __T("userspace counter width not set", pc->pmc_width >= 32); 163241675Suqs#endif 164241675Suqs 165241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 166241675Suqs __T("failed to read value for evsel", counts.val != 0); 167241675Suqs 168241675Suqs for (i = 0; i < 5; i++) { 169241675Suqs volatile int count = 0x10000 << i; 170241675Suqs __u64 start, end, last = 0; 171241675Suqs 172241675Suqs __T_VERBOSE("\tloop = %u, ", count); 173241675Suqs 174241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 175241675Suqs start = counts.val; 176241675Suqs 177241675Suqs while (count--) ; 178241675Suqs 179241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 180241675Suqs end = counts.val; 181241675Suqs 182241675Suqs __T("invalid counter data", (end - start) > last); 183241675Suqs last = end - start; 184241675Suqs __T_VERBOSE("count = %llu\n", end - start); 185241675Suqs } 186241675Suqs 187241675Suqs perf_evsel__munmap(evsel); 188241675Suqs perf_evsel__close(evsel); 189241675Suqs perf_evsel__delete(evsel); 190241675Suqs 191241675Suqs perf_thread_map__put(threads); 192241675Suqs return 0; 193241675Suqs} 194241675Suqs 195241675Suqsstatic int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads) 196241675Suqs{ 197241675Suqs struct perf_evsel *evsel; 198241675Suqs struct perf_counts_values counts; 199241675Suqs volatile int count = 0x100000; 200241675Suqs int err; 201241675Suqs 202241675Suqs evsel = perf_evsel__new(attr); 203241675Suqs __T("failed to create evsel", evsel); 204241675Suqs 205241675Suqs /* skip old kernels that don't support the format */ 206241675Suqs err = perf_evsel__open(evsel, NULL, threads); 207241675Suqs if (err < 0) 208241675Suqs return 0; 209241675Suqs 210241675Suqs while (count--) ; 211241675Suqs 212241675Suqs memset(&counts, -1, sizeof(counts)); 213241675Suqs perf_evsel__read(evsel, 0, 0, &counts); 214241675Suqs 215241675Suqs __T("failed to read value", counts.val); 216241675Suqs if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 217241675Suqs __T("failed to read TOTAL_TIME_ENABLED", counts.ena); 218241675Suqs if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 219241675Suqs __T("failed to read TOTAL_TIME_RUNNING", counts.run); 220241675Suqs if (attr->read_format & PERF_FORMAT_ID) 221241675Suqs __T("failed to read ID", counts.id); 222241675Suqs if (attr->read_format & PERF_FORMAT_LOST) 223241675Suqs __T("failed to read LOST", counts.lost == 0); 224241675Suqs 225241675Suqs perf_evsel__close(evsel); 226241675Suqs perf_evsel__delete(evsel); 227241675Suqs return 0; 228241675Suqs} 229241675Suqs 230241675Suqsstatic int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads) 231241675Suqs{ 232241675Suqs struct perf_evsel *leader, *member; 233241675Suqs struct perf_counts_values counts; 234241675Suqs volatile int count = 0x100000; 235241675Suqs int err; 236241675Suqs 237241675Suqs attr->read_format |= PERF_FORMAT_GROUP; 238241675Suqs leader = perf_evsel__new(attr); 239241675Suqs __T("failed to create leader", leader); 240241675Suqs 241241675Suqs attr->read_format &= ~PERF_FORMAT_GROUP; 242241675Suqs member = perf_evsel__new(attr); 243241675Suqs __T("failed to create member", member); 244241675Suqs 245241675Suqs member->leader = leader; 246241675Suqs leader->nr_members = 2; 247241675Suqs 248241675Suqs /* skip old kernels that don't support the format */ 249241675Suqs err = perf_evsel__open(leader, NULL, threads); 250241675Suqs if (err < 0) 251241675Suqs return 0; 252241675Suqs err = perf_evsel__open(member, NULL, threads); 253241675Suqs if (err < 0) 254241675Suqs return 0; 255241675Suqs 256241675Suqs while (count--) ; 257241675Suqs 258241675Suqs memset(&counts, -1, sizeof(counts)); 259241675Suqs perf_evsel__read(leader, 0, 0, &counts); 260241675Suqs 261241675Suqs __T("failed to read leader value", counts.val); 262241675Suqs if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 263241675Suqs __T("failed to read leader TOTAL_TIME_ENABLED", counts.ena); 264241675Suqs if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 265241675Suqs __T("failed to read leader TOTAL_TIME_RUNNING", counts.run); 266241675Suqs if (attr->read_format & PERF_FORMAT_ID) 267241675Suqs __T("failed to read leader ID", counts.id); 268241675Suqs if (attr->read_format & PERF_FORMAT_LOST) 269241675Suqs __T("failed to read leader LOST", counts.lost == 0); 270241675Suqs 271241675Suqs memset(&counts, -1, sizeof(counts)); 272241675Suqs perf_evsel__read(member, 0, 0, &counts); 273241675Suqs 274241675Suqs __T("failed to read member value", counts.val); 275241675Suqs if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 276241675Suqs __T("failed to read member TOTAL_TIME_ENABLED", counts.ena); 277241675Suqs if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 278241675Suqs __T("failed to read member TOTAL_TIME_RUNNING", counts.run); 279241675Suqs if (attr->read_format & PERF_FORMAT_ID) 280241675Suqs __T("failed to read member ID", counts.id); 281241675Suqs if (attr->read_format & PERF_FORMAT_LOST) 282241675Suqs __T("failed to read member LOST", counts.lost == 0); 283241675Suqs 284241675Suqs perf_evsel__close(member); 285241675Suqs perf_evsel__close(leader); 286241675Suqs perf_evsel__delete(member); 287241675Suqs perf_evsel__delete(leader); 288241675Suqs return 0; 289241675Suqs} 290241675Suqs 291241675Suqsstatic int test_stat_read_format(void) 292241675Suqs{ 293241675Suqs struct perf_thread_map *threads; 294241675Suqs struct perf_event_attr attr = { 295241675Suqs .type = PERF_TYPE_SOFTWARE, 296241675Suqs .config = PERF_COUNT_SW_TASK_CLOCK, 297241675Suqs }; 298241675Suqs int err, i; 299241675Suqs 300241675Suqs#define FMT(_fmt) PERF_FORMAT_ ## _fmt 301241675Suqs#define FMT_TIME (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING)) 302241675Suqs 303241675Suqs uint64_t test_formats [] = { 304241675Suqs 0, 305241675Suqs FMT_TIME, 306241675Suqs FMT(ID), 307241675Suqs FMT(LOST), 308241675Suqs FMT_TIME | FMT(ID), 309241675Suqs FMT_TIME | FMT(LOST), 310241675Suqs FMT_TIME | FMT(ID) | FMT(LOST), 311241675Suqs FMT(ID) | FMT(LOST), 312241675Suqs }; 313241675Suqs 314241675Suqs#undef FMT 315241675Suqs#undef FMT_TIME 316241675Suqs 317241675Suqs threads = perf_thread_map__new_dummy(); 318241675Suqs __T("failed to create threads", threads); 319241675Suqs 320241675Suqs perf_thread_map__set_pid(threads, 0, 0); 321241675Suqs 322241675Suqs for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) { 323241675Suqs attr.read_format = test_formats[i]; 324241675Suqs __T_VERBOSE("testing single read with read_format: %lx\n", 325241675Suqs (unsigned long)test_formats[i]); 326241675Suqs 327241675Suqs err = test_stat_read_format_single(&attr, threads); 328241675Suqs __T("failed to read single format", err == 0); 329241675Suqs } 330241675Suqs 331241675Suqs perf_thread_map__put(threads); 332241675Suqs 333241675Suqs threads = perf_thread_map__new_array(2, NULL); 334241675Suqs __T("failed to create threads", threads); 335241675Suqs 336241675Suqs perf_thread_map__set_pid(threads, 0, 0); 337241675Suqs perf_thread_map__set_pid(threads, 1, 0); 338241675Suqs 339241675Suqs for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) { 340241675Suqs attr.read_format = test_formats[i]; 341241675Suqs __T_VERBOSE("testing group read with read_format: %lx\n", 342241675Suqs (unsigned long)test_formats[i]); 343241675Suqs 344241675Suqs err = test_stat_read_format_group(&attr, threads); 345241675Suqs __T("failed to read group format", err == 0); 346241675Suqs } 347241675Suqs 348241675Suqs perf_thread_map__put(threads); 349241675Suqs return 0; 350241675Suqs} 351241675Suqs 352241675Suqsint test_evsel(int argc, char **argv) 353241675Suqs{ 354241675Suqs __T_START; 355241675Suqs 356241675Suqs libperf_init(libperf_print); 357241675Suqs 358241675Suqs test_stat_cpu(); 359241675Suqs test_stat_thread(); 360241675Suqs test_stat_thread_enable(); 361241675Suqs test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS); 362241675Suqs test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES); 363241675Suqs test_stat_read_format(); 364241675Suqs 365241675Suqs __T_END; 366241675Suqs return tests_failed == 0 ? 0 : -1; 367241675Suqs} 368241675Suqs