Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <stdarg.h>
0003 #include <stdio.h>
0004 #include <string.h>
0005 #include <linux/perf_event.h>
0006 #include <linux/kernel.h>
0007 #include <perf/cpumap.h>
0008 #include <perf/threadmap.h>
0009 #include <perf/evsel.h>
0010 #include <internal/evsel.h>
0011 #include <internal/tests.h>
0012 #include "tests.h"
0013 
0014 static int libperf_print(enum libperf_print_level level,
0015              const char *fmt, va_list ap)
0016 {
0017     return vfprintf(stderr, fmt, ap);
0018 }
0019 
0020 static int test_stat_cpu(void)
0021 {
0022     struct perf_cpu_map *cpus;
0023     struct perf_evsel *evsel;
0024     struct perf_event_attr attr = {
0025         .type   = PERF_TYPE_SOFTWARE,
0026         .config = PERF_COUNT_SW_CPU_CLOCK,
0027     };
0028     int err, idx;
0029 
0030     cpus = perf_cpu_map__new(NULL);
0031     __T("failed to create cpus", cpus);
0032 
0033     evsel = perf_evsel__new(&attr);
0034     __T("failed to create evsel", evsel);
0035 
0036     err = perf_evsel__open(evsel, cpus, NULL);
0037     __T("failed to open evsel", err == 0);
0038 
0039     for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
0040         struct perf_counts_values counts = { .val = 0 };
0041 
0042         perf_evsel__read(evsel, idx, 0, &counts);
0043         __T("failed to read value for evsel", counts.val != 0);
0044     }
0045 
0046     perf_evsel__close(evsel);
0047     perf_evsel__delete(evsel);
0048 
0049     perf_cpu_map__put(cpus);
0050     return 0;
0051 }
0052 
0053 static int test_stat_thread(void)
0054 {
0055     struct perf_counts_values counts = { .val = 0 };
0056     struct perf_thread_map *threads;
0057     struct perf_evsel *evsel;
0058     struct perf_event_attr attr = {
0059         .type   = PERF_TYPE_SOFTWARE,
0060         .config = PERF_COUNT_SW_TASK_CLOCK,
0061     };
0062     int err;
0063 
0064     threads = perf_thread_map__new_dummy();
0065     __T("failed to create threads", threads);
0066 
0067     perf_thread_map__set_pid(threads, 0, 0);
0068 
0069     evsel = perf_evsel__new(&attr);
0070     __T("failed to create evsel", evsel);
0071 
0072     err = perf_evsel__open(evsel, NULL, threads);
0073     __T("failed to open evsel", err == 0);
0074 
0075     perf_evsel__read(evsel, 0, 0, &counts);
0076     __T("failed to read value for evsel", counts.val != 0);
0077 
0078     perf_evsel__close(evsel);
0079     perf_evsel__delete(evsel);
0080 
0081     perf_thread_map__put(threads);
0082     return 0;
0083 }
0084 
0085 static int test_stat_thread_enable(void)
0086 {
0087     struct perf_counts_values counts = { .val = 0 };
0088     struct perf_thread_map *threads;
0089     struct perf_evsel *evsel;
0090     struct perf_event_attr attr = {
0091         .type     = PERF_TYPE_SOFTWARE,
0092         .config   = PERF_COUNT_SW_TASK_CLOCK,
0093         .disabled = 1,
0094     };
0095     int err;
0096 
0097     threads = perf_thread_map__new_dummy();
0098     __T("failed to create threads", threads);
0099 
0100     perf_thread_map__set_pid(threads, 0, 0);
0101 
0102     evsel = perf_evsel__new(&attr);
0103     __T("failed to create evsel", evsel);
0104 
0105     err = perf_evsel__open(evsel, NULL, threads);
0106     __T("failed to open evsel", err == 0);
0107 
0108     perf_evsel__read(evsel, 0, 0, &counts);
0109     __T("failed to read value for evsel", counts.val == 0);
0110 
0111     err = perf_evsel__enable(evsel);
0112     __T("failed to enable evsel", err == 0);
0113 
0114     perf_evsel__read(evsel, 0, 0, &counts);
0115     __T("failed to read value for evsel", counts.val != 0);
0116 
0117     err = perf_evsel__disable(evsel);
0118     __T("failed to enable evsel", err == 0);
0119 
0120     perf_evsel__close(evsel);
0121     perf_evsel__delete(evsel);
0122 
0123     perf_thread_map__put(threads);
0124     return 0;
0125 }
0126 
0127 static int test_stat_user_read(int event)
0128 {
0129     struct perf_counts_values counts = { .val = 0 };
0130     struct perf_thread_map *threads;
0131     struct perf_evsel *evsel;
0132     struct perf_event_mmap_page *pc;
0133     struct perf_event_attr attr = {
0134         .type   = PERF_TYPE_HARDWARE,
0135         .config = event,
0136 #ifdef __aarch64__
0137         .config1 = 0x2,     /* Request user access */
0138 #endif
0139     };
0140     int err, i;
0141 
0142     threads = perf_thread_map__new_dummy();
0143     __T("failed to create threads", threads);
0144 
0145     perf_thread_map__set_pid(threads, 0, 0);
0146 
0147     evsel = perf_evsel__new(&attr);
0148     __T("failed to create evsel", evsel);
0149 
0150     err = perf_evsel__open(evsel, NULL, threads);
0151     __T("failed to open evsel", err == 0);
0152 
0153     err = perf_evsel__mmap(evsel, 0);
0154     __T("failed to mmap evsel", err == 0);
0155 
0156     pc = perf_evsel__mmap_base(evsel, 0, 0);
0157     __T("failed to get mmapped address", pc);
0158 
0159 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
0160     __T("userspace counter access not supported", pc->cap_user_rdpmc);
0161     __T("userspace counter access not enabled", pc->index);
0162     __T("userspace counter width not set", pc->pmc_width >= 32);
0163 #endif
0164 
0165     perf_evsel__read(evsel, 0, 0, &counts);
0166     __T("failed to read value for evsel", counts.val != 0);
0167 
0168     for (i = 0; i < 5; i++) {
0169         volatile int count = 0x10000 << i;
0170         __u64 start, end, last = 0;
0171 
0172         __T_VERBOSE("\tloop = %u, ", count);
0173 
0174         perf_evsel__read(evsel, 0, 0, &counts);
0175         start = counts.val;
0176 
0177         while (count--) ;
0178 
0179         perf_evsel__read(evsel, 0, 0, &counts);
0180         end = counts.val;
0181 
0182         __T("invalid counter data", (end - start) > last);
0183         last = end - start;
0184         __T_VERBOSE("count = %llu\n", end - start);
0185     }
0186 
0187     perf_evsel__munmap(evsel);
0188     perf_evsel__close(evsel);
0189     perf_evsel__delete(evsel);
0190 
0191     perf_thread_map__put(threads);
0192     return 0;
0193 }
0194 
0195 static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads)
0196 {
0197     struct perf_evsel *evsel;
0198     struct perf_counts_values counts;
0199     volatile int count = 0x100000;
0200     int err;
0201 
0202     evsel = perf_evsel__new(attr);
0203     __T("failed to create evsel", evsel);
0204 
0205     /* skip old kernels that don't support the format */
0206     err = perf_evsel__open(evsel, NULL, threads);
0207     if (err < 0)
0208         return 0;
0209 
0210     while (count--) ;
0211 
0212     memset(&counts, -1, sizeof(counts));
0213     perf_evsel__read(evsel, 0, 0, &counts);
0214 
0215     __T("failed to read value", counts.val);
0216     if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
0217         __T("failed to read TOTAL_TIME_ENABLED", counts.ena);
0218     if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
0219         __T("failed to read TOTAL_TIME_RUNNING", counts.run);
0220     if (attr->read_format & PERF_FORMAT_ID)
0221         __T("failed to read ID", counts.id);
0222     if (attr->read_format & PERF_FORMAT_LOST)
0223         __T("failed to read LOST", counts.lost == 0);
0224 
0225     perf_evsel__close(evsel);
0226     perf_evsel__delete(evsel);
0227     return 0;
0228 }
0229 
0230 static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads)
0231 {
0232     struct perf_evsel *leader, *member;
0233     struct perf_counts_values counts;
0234     volatile int count = 0x100000;
0235     int err;
0236 
0237     attr->read_format |= PERF_FORMAT_GROUP;
0238     leader = perf_evsel__new(attr);
0239     __T("failed to create leader", leader);
0240 
0241     attr->read_format &= ~PERF_FORMAT_GROUP;
0242     member = perf_evsel__new(attr);
0243     __T("failed to create member", member);
0244 
0245     member->leader = leader;
0246     leader->nr_members = 2;
0247 
0248     /* skip old kernels that don't support the format */
0249     err = perf_evsel__open(leader, NULL, threads);
0250     if (err < 0)
0251         return 0;
0252     err = perf_evsel__open(member, NULL, threads);
0253     if (err < 0)
0254         return 0;
0255 
0256     while (count--) ;
0257 
0258     memset(&counts, -1, sizeof(counts));
0259     perf_evsel__read(leader, 0, 0, &counts);
0260 
0261     __T("failed to read leader value", counts.val);
0262     if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
0263         __T("failed to read leader TOTAL_TIME_ENABLED", counts.ena);
0264     if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
0265         __T("failed to read leader TOTAL_TIME_RUNNING", counts.run);
0266     if (attr->read_format & PERF_FORMAT_ID)
0267         __T("failed to read leader ID", counts.id);
0268     if (attr->read_format & PERF_FORMAT_LOST)
0269         __T("failed to read leader LOST", counts.lost == 0);
0270 
0271     memset(&counts, -1, sizeof(counts));
0272     perf_evsel__read(member, 0, 0, &counts);
0273 
0274     __T("failed to read member value", counts.val);
0275     if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
0276         __T("failed to read member TOTAL_TIME_ENABLED", counts.ena);
0277     if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
0278         __T("failed to read member TOTAL_TIME_RUNNING", counts.run);
0279     if (attr->read_format & PERF_FORMAT_ID)
0280         __T("failed to read member ID", counts.id);
0281     if (attr->read_format & PERF_FORMAT_LOST)
0282         __T("failed to read member LOST", counts.lost == 0);
0283 
0284     perf_evsel__close(member);
0285     perf_evsel__close(leader);
0286     perf_evsel__delete(member);
0287     perf_evsel__delete(leader);
0288     return 0;
0289 }
0290 
0291 static int test_stat_read_format(void)
0292 {
0293     struct perf_thread_map *threads;
0294     struct perf_event_attr attr = {
0295         .type   = PERF_TYPE_SOFTWARE,
0296         .config = PERF_COUNT_SW_TASK_CLOCK,
0297     };
0298     int err, i;
0299 
0300 #define FMT(_fmt)  PERF_FORMAT_ ## _fmt
0301 #define FMT_TIME  (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING))
0302 
0303     uint64_t test_formats [] = {
0304         0,
0305         FMT_TIME,
0306         FMT(ID),
0307         FMT(LOST),
0308         FMT_TIME | FMT(ID),
0309         FMT_TIME | FMT(LOST),
0310         FMT_TIME | FMT(ID) | FMT(LOST),
0311         FMT(ID) | FMT(LOST),
0312     };
0313 
0314 #undef FMT
0315 #undef FMT_TIME
0316 
0317     threads = perf_thread_map__new_dummy();
0318     __T("failed to create threads", threads);
0319 
0320     perf_thread_map__set_pid(threads, 0, 0);
0321 
0322     for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
0323         attr.read_format = test_formats[i];
0324         __T_VERBOSE("testing single read with read_format: %lx\n",
0325                 (unsigned long)test_formats[i]);
0326 
0327         err = test_stat_read_format_single(&attr, threads);
0328         __T("failed to read single format", err == 0);
0329     }
0330 
0331     perf_thread_map__put(threads);
0332 
0333     threads = perf_thread_map__new_array(2, NULL);
0334     __T("failed to create threads", threads);
0335 
0336     perf_thread_map__set_pid(threads, 0, 0);
0337     perf_thread_map__set_pid(threads, 1, 0);
0338 
0339     for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
0340         attr.read_format = test_formats[i];
0341         __T_VERBOSE("testing group read with read_format: %lx\n",
0342                 (unsigned long)test_formats[i]);
0343 
0344         err = test_stat_read_format_group(&attr, threads);
0345         __T("failed to read group format", err == 0);
0346     }
0347 
0348     perf_thread_map__put(threads);
0349     return 0;
0350 }
0351 
0352 int test_evsel(int argc, char **argv)
0353 {
0354     __T_START;
0355 
0356     libperf_init(libperf_print);
0357 
0358     test_stat_cpu();
0359     test_stat_thread();
0360     test_stat_thread_enable();
0361     test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
0362     test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
0363     test_stat_read_format();
0364 
0365     __T_END;
0366     return tests_failed == 0 ? 0 : -1;
0367 }