linux/tools/perf/builtin-test.c
<<
>>
Prefs
   1/*
   2 * builtin-test.c
   3 *
   4 * Builtin regression testing command: ever growing number of sanity tests
   5 */
   6#include "builtin.h"
   7
   8#include "util/cache.h"
   9#include "util/debug.h"
  10#include "util/debugfs.h"
  11#include "util/evlist.h"
  12#include "util/parse-options.h"
  13#include "util/parse-events.h"
  14#include "util/symbol.h"
  15#include "util/thread_map.h"
  16#include "util/pmu.h"
  17#include "../../include/linux/hw_breakpoint.h"
  18
  19#include <sys/mman.h>
  20
  21static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
  22{
  23        bool *visited = symbol__priv(sym);
  24        *visited = true;
  25        return 0;
  26}
  27
  28static int test__vmlinux_matches_kallsyms(void)
  29{
  30        int err = -1;
  31        struct rb_node *nd;
  32        struct symbol *sym;
  33        struct map *kallsyms_map, *vmlinux_map;
  34        struct machine kallsyms, vmlinux;
  35        enum map_type type = MAP__FUNCTION;
  36        long page_size = sysconf(_SC_PAGE_SIZE);
  37        struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
  38
  39        /*
  40         * Step 1:
  41         *
  42         * Init the machines that will hold kernel, modules obtained from
  43         * both vmlinux + .ko files and from /proc/kallsyms split by modules.
  44         */
  45        machine__init(&kallsyms, "", HOST_KERNEL_ID);
  46        machine__init(&vmlinux, "", HOST_KERNEL_ID);
  47
  48        /*
  49         * Step 2:
  50         *
  51         * Create the kernel maps for kallsyms and the DSO where we will then
  52         * load /proc/kallsyms. Also create the modules maps from /proc/modules
  53         * and find the .ko files that match them in /lib/modules/`uname -r`/.
  54         */
  55        if (machine__create_kernel_maps(&kallsyms) < 0) {
  56                pr_debug("machine__create_kernel_maps ");
  57                return -1;
  58        }
  59
  60        /*
  61         * Step 3:
  62         *
  63         * Load and split /proc/kallsyms into multiple maps, one per module.
  64         */
  65        if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {
  66                pr_debug("dso__load_kallsyms ");
  67                goto out;
  68        }
  69
  70        /*
  71         * Step 4:
  72         *
  73         * kallsyms will be internally on demand sorted by name so that we can
  74         * find the reference relocation * symbol, i.e. the symbol we will use
  75         * to see if the running kernel was relocated by checking if it has the
  76         * same value in the vmlinux file we load.
  77         */
  78        kallsyms_map = machine__kernel_map(&kallsyms, type);
  79
  80        sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
  81        if (sym == NULL) {
  82                pr_debug("dso__find_symbol_by_name ");
  83                goto out;
  84        }
  85
  86        ref_reloc_sym.addr = sym->start;
  87
  88        /*
  89         * Step 5:
  90         *
  91         * Now repeat step 2, this time for the vmlinux file we'll auto-locate.
  92         */
  93        if (machine__create_kernel_maps(&vmlinux) < 0) {
  94                pr_debug("machine__create_kernel_maps ");
  95                goto out;
  96        }
  97
  98        vmlinux_map = machine__kernel_map(&vmlinux, type);
  99        map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
 100
 101        /*
 102         * Step 6:
 103         *
 104         * Locate a vmlinux file in the vmlinux path that has a buildid that
 105         * matches the one of the running kernel.
 106         *
 107         * While doing that look if we find the ref reloc symbol, if we find it
 108         * we'll have its ref_reloc_symbol.unrelocated_addr and then
 109         * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
 110         * to fixup the symbols.
 111         */
 112        if (machine__load_vmlinux_path(&vmlinux, type,
 113                                       vmlinux_matches_kallsyms_filter) <= 0) {
 114                pr_debug("machine__load_vmlinux_path ");
 115                goto out;
 116        }
 117
 118        err = 0;
 119        /*
 120         * Step 7:
 121         *
 122         * Now look at the symbols in the vmlinux DSO and check if we find all of them
 123         * in the kallsyms dso. For the ones that are in both, check its names and
 124         * end addresses too.
 125         */
 126        for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
 127                struct symbol *pair, *first_pair;
 128                bool backwards = true;
 129
 130                sym  = rb_entry(nd, struct symbol, rb_node);
 131
 132                if (sym->start == sym->end)
 133                        continue;
 134
 135                first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
 136                pair = first_pair;
 137
 138                if (pair && pair->start == sym->start) {
 139next_pair:
 140                        if (strcmp(sym->name, pair->name) == 0) {
 141                                /*
 142                                 * kallsyms don't have the symbol end, so we
 143                                 * set that by using the next symbol start - 1,
 144                                 * in some cases we get this up to a page
 145                                 * wrong, trace_kmalloc when I was developing
 146                                 * this code was one such example, 2106 bytes
 147                                 * off the real size. More than that and we
 148                                 * _really_ have a problem.
 149                                 */
 150                                s64 skew = sym->end - pair->end;
 151                                if (llabs(skew) < page_size)
 152                                        continue;
 153
 154                                pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
 155                                         sym->start, sym->name, sym->end, pair->end);
 156                        } else {
 157                                struct rb_node *nnd;
 158detour:
 159                                nnd = backwards ? rb_prev(&pair->rb_node) :
 160                                                  rb_next(&pair->rb_node);
 161                                if (nnd) {
 162                                        struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
 163
 164                                        if (next->start == sym->start) {
 165                                                pair = next;
 166                                                goto next_pair;
 167                                        }
 168                                }
 169
 170                                if (backwards) {
 171                                        backwards = false;
 172                                        pair = first_pair;
 173                                        goto detour;
 174                                }
 175
 176                                pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
 177                                         sym->start, sym->name, pair->name);
 178                        }
 179                } else
 180                        pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
 181
 182                err = -1;
 183        }
 184
 185        if (!verbose)
 186                goto out;
 187
 188        pr_info("Maps only in vmlinux:\n");
 189
 190        for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
 191                struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
 192                /*
 193                 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
 194                 * the kernel will have the path for the vmlinux file being used,
 195                 * so use the short name, less descriptive but the same ("[kernel]" in
 196                 * both cases.
 197                 */
 198                pair = map_groups__find_by_name(&kallsyms.kmaps, type,
 199                                                (pos->dso->kernel ?
 200                                                        pos->dso->short_name :
 201                                                        pos->dso->name));
 202                if (pair)
 203                        pair->priv = 1;
 204                else
 205                        map__fprintf(pos, stderr);
 206        }
 207
 208        pr_info("Maps in vmlinux with a different name in kallsyms:\n");
 209
 210        for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
 211                struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
 212
 213                pair = map_groups__find(&kallsyms.kmaps, type, pos->start);
 214                if (pair == NULL || pair->priv)
 215                        continue;
 216
 217                if (pair->start == pos->start) {
 218                        pair->priv = 1;
 219                        pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
 220                                pos->start, pos->end, pos->pgoff, pos->dso->name);
 221                        if (pos->pgoff != pair->pgoff || pos->end != pair->end)
 222                                pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
 223                                        pair->start, pair->end, pair->pgoff);
 224                        pr_info(" %s\n", pair->dso->name);
 225                        pair->priv = 1;
 226                }
 227        }
 228
 229        pr_info("Maps only in kallsyms:\n");
 230
 231        for (nd = rb_first(&kallsyms.kmaps.maps[type]);
 232             nd; nd = rb_next(nd)) {
 233                struct map *pos = rb_entry(nd, struct map, rb_node);
 234
 235                if (!pos->priv)
 236                        map__fprintf(pos, stderr);
 237        }
 238out:
 239        return err;
 240}
 241
 242#include "util/cpumap.h"
 243#include "util/evsel.h"
 244#include <sys/types.h>
 245
 246static int trace_event__id(const char *evname)
 247{
 248        char *filename;
 249        int err = -1, fd;
 250
 251        if (asprintf(&filename,
 252                     "%s/syscalls/%s/id",
 253                     tracing_events_path, evname) < 0)
 254                return -1;
 255
 256        fd = open(filename, O_RDONLY);
 257        if (fd >= 0) {
 258                char id[16];
 259                if (read(fd, id, sizeof(id)) > 0)
 260                        err = atoi(id);
 261                close(fd);
 262        }
 263
 264        free(filename);
 265        return err;
 266}
 267
 268static int test__open_syscall_event(void)
 269{
 270        int err = -1, fd;
 271        struct thread_map *threads;
 272        struct perf_evsel *evsel;
 273        struct perf_event_attr attr;
 274        unsigned int nr_open_calls = 111, i;
 275        int id = trace_event__id("sys_enter_open");
 276
 277        if (id < 0) {
 278                pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
 279                return -1;
 280        }
 281
 282        threads = thread_map__new(-1, getpid(), UINT_MAX);
 283        if (threads == NULL) {
 284                pr_debug("thread_map__new\n");
 285                return -1;
 286        }
 287
 288        memset(&attr, 0, sizeof(attr));
 289        attr.type = PERF_TYPE_TRACEPOINT;
 290        attr.config = id;
 291        evsel = perf_evsel__new(&attr, 0);
 292        if (evsel == NULL) {
 293                pr_debug("perf_evsel__new\n");
 294                goto out_thread_map_delete;
 295        }
 296
 297        if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) {
 298                pr_debug("failed to open counter: %s, "
 299                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
 300                         strerror(errno));
 301                goto out_evsel_delete;
 302        }
 303
 304        for (i = 0; i < nr_open_calls; ++i) {
 305                fd = open("/etc/passwd", O_RDONLY);
 306                close(fd);
 307        }
 308
 309        if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
 310                pr_debug("perf_evsel__read_on_cpu\n");
 311                goto out_close_fd;
 312        }
 313
 314        if (evsel->counts->cpu[0].val != nr_open_calls) {
 315                pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
 316                         nr_open_calls, evsel->counts->cpu[0].val);
 317                goto out_close_fd;
 318        }
 319        
 320        err = 0;
 321out_close_fd:
 322        perf_evsel__close_fd(evsel, 1, threads->nr);
 323out_evsel_delete:
 324        perf_evsel__delete(evsel);
 325out_thread_map_delete:
 326        thread_map__delete(threads);
 327        return err;
 328}
 329
 330#include <sched.h>
 331
 332static int test__open_syscall_event_on_all_cpus(void)
 333{
 334        int err = -1, fd, cpu;
 335        struct thread_map *threads;
 336        struct cpu_map *cpus;
 337        struct perf_evsel *evsel;
 338        struct perf_event_attr attr;
 339        unsigned int nr_open_calls = 111, i;
 340        cpu_set_t cpu_set;
 341        int id = trace_event__id("sys_enter_open");
 342
 343        if (id < 0) {
 344                pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
 345                return -1;
 346        }
 347
 348        threads = thread_map__new(-1, getpid(), UINT_MAX);
 349        if (threads == NULL) {
 350                pr_debug("thread_map__new\n");
 351                return -1;
 352        }
 353
 354        cpus = cpu_map__new(NULL);
 355        if (cpus == NULL) {
 356                pr_debug("cpu_map__new\n");
 357                goto out_thread_map_delete;
 358        }
 359
 360
 361        CPU_ZERO(&cpu_set);
 362
 363        memset(&attr, 0, sizeof(attr));
 364        attr.type = PERF_TYPE_TRACEPOINT;
 365        attr.config = id;
 366        evsel = perf_evsel__new(&attr, 0);
 367        if (evsel == NULL) {
 368                pr_debug("perf_evsel__new\n");
 369                goto out_thread_map_delete;
 370        }
 371
 372        if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) {
 373                pr_debug("failed to open counter: %s, "
 374                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
 375                         strerror(errno));
 376                goto out_evsel_delete;
 377        }
 378
 379        for (cpu = 0; cpu < cpus->nr; ++cpu) {
 380                unsigned int ncalls = nr_open_calls + cpu;
 381                /*
 382                 * XXX eventually lift this restriction in a way that
 383                 * keeps perf building on older glibc installations
 384                 * without CPU_ALLOC. 1024 cpus in 2010 still seems
 385                 * a reasonable upper limit tho :-)
 386                 */
 387                if (cpus->map[cpu] >= CPU_SETSIZE) {
 388                        pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
 389                        continue;
 390                }
 391
 392                CPU_SET(cpus->map[cpu], &cpu_set);
 393                if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
 394                        pr_debug("sched_setaffinity() failed on CPU %d: %s ",
 395                                 cpus->map[cpu],
 396                                 strerror(errno));
 397                        goto out_close_fd;
 398                }
 399                for (i = 0; i < ncalls; ++i) {
 400                        fd = open("/etc/passwd", O_RDONLY);
 401                        close(fd);
 402                }
 403                CPU_CLR(cpus->map[cpu], &cpu_set);
 404        }
 405
 406        /*
 407         * Here we need to explicitely preallocate the counts, as if
 408         * we use the auto allocation it will allocate just for 1 cpu,
 409         * as we start by cpu 0.
 410         */
 411        if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
 412                pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
 413                goto out_close_fd;
 414        }
 415
 416        err = 0;
 417
 418        for (cpu = 0; cpu < cpus->nr; ++cpu) {
 419                unsigned int expected;
 420
 421                if (cpus->map[cpu] >= CPU_SETSIZE)
 422                        continue;
 423
 424                if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
 425                        pr_debug("perf_evsel__read_on_cpu\n");
 426                        err = -1;
 427                        break;
 428                }
 429
 430                expected = nr_open_calls + cpu;
 431                if (evsel->counts->cpu[cpu].val != expected) {
 432                        pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
 433                                 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
 434                        err = -1;
 435                }
 436        }
 437
 438out_close_fd:
 439        perf_evsel__close_fd(evsel, 1, threads->nr);
 440out_evsel_delete:
 441        perf_evsel__delete(evsel);
 442out_thread_map_delete:
 443        thread_map__delete(threads);
 444        return err;
 445}
 446
 447/*
 448 * This test will generate random numbers of calls to some getpid syscalls,
 449 * then establish an mmap for a group of events that are created to monitor
 450 * the syscalls.
 451 *
 452 * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
 453 * sample.id field to map back to its respective perf_evsel instance.
 454 *
 455 * Then it checks if the number of syscalls reported as perf events by
 456 * the kernel corresponds to the number of syscalls made.
 457 */
 458static int test__basic_mmap(void)
 459{
 460        int err = -1;
 461        union perf_event *event;
 462        struct thread_map *threads;
 463        struct cpu_map *cpus;
 464        struct perf_evlist *evlist;
 465        struct perf_event_attr attr = {
 466                .type           = PERF_TYPE_TRACEPOINT,
 467                .read_format    = PERF_FORMAT_ID,
 468                .sample_type    = PERF_SAMPLE_ID,
 469                .watermark      = 0,
 470        };
 471        cpu_set_t cpu_set;
 472        const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
 473                                        "getpgid", };
 474        pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
 475                                      (void*)getpgid };
 476#define nsyscalls ARRAY_SIZE(syscall_names)
 477        int ids[nsyscalls];
 478        unsigned int nr_events[nsyscalls],
 479                     expected_nr_events[nsyscalls], i, j;
 480        struct perf_evsel *evsels[nsyscalls], *evsel;
 481        int sample_size = __perf_evsel__sample_size(attr.sample_type);
 482
 483        for (i = 0; i < nsyscalls; ++i) {
 484                char name[64];
 485
 486                snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
 487                ids[i] = trace_event__id(name);
 488                if (ids[i] < 0) {
 489                        pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
 490                        return -1;
 491                }
 492                nr_events[i] = 0;
 493                expected_nr_events[i] = random() % 257;
 494        }
 495
 496        threads = thread_map__new(-1, getpid(), UINT_MAX);
 497        if (threads == NULL) {
 498                pr_debug("thread_map__new\n");
 499                return -1;
 500        }
 501
 502        cpus = cpu_map__new(NULL);
 503        if (cpus == NULL) {
 504                pr_debug("cpu_map__new\n");
 505                goto out_free_threads;
 506        }
 507
 508        CPU_ZERO(&cpu_set);
 509        CPU_SET(cpus->map[0], &cpu_set);
 510        sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
 511        if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
 512                pr_debug("sched_setaffinity() failed on CPU %d: %s ",
 513                         cpus->map[0], strerror(errno));
 514                goto out_free_cpus;
 515        }
 516
 517        evlist = perf_evlist__new(cpus, threads);
 518        if (evlist == NULL) {
 519                pr_debug("perf_evlist__new\n");
 520                goto out_free_cpus;
 521        }
 522
 523        /* anonymous union fields, can't be initialized above */
 524        attr.wakeup_events = 1;
 525        attr.sample_period = 1;
 526
 527        for (i = 0; i < nsyscalls; ++i) {
 528                attr.config = ids[i];
 529                evsels[i] = perf_evsel__new(&attr, i);
 530                if (evsels[i] == NULL) {
 531                        pr_debug("perf_evsel__new\n");
 532                        goto out_free_evlist;
 533                }
 534
 535                perf_evlist__add(evlist, evsels[i]);
 536
 537                if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) {
 538                        pr_debug("failed to open counter: %s, "
 539                                 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
 540                                 strerror(errno));
 541                        goto out_close_fd;
 542                }
 543        }
 544
 545        if (perf_evlist__mmap(evlist, 128, true) < 0) {
 546                pr_debug("failed to mmap events: %d (%s)\n", errno,
 547                         strerror(errno));
 548                goto out_close_fd;
 549        }
 550
 551        for (i = 0; i < nsyscalls; ++i)
 552                for (j = 0; j < expected_nr_events[i]; ++j) {
 553                        int foo = syscalls[i]();
 554                        ++foo;
 555                }
 556
 557        while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
 558                struct perf_sample sample;
 559
 560                if (event->header.type != PERF_RECORD_SAMPLE) {
 561                        pr_debug("unexpected %s event\n",
 562                                 perf_event__name(event->header.type));
 563                        goto out_munmap;
 564                }
 565
 566                err = perf_event__parse_sample(event, attr.sample_type, sample_size,
 567                                               false, &sample, false);
 568                if (err) {
 569                        pr_err("Can't parse sample, err = %d\n", err);
 570                        goto out_munmap;
 571                }
 572
 573                evsel = perf_evlist__id2evsel(evlist, sample.id);
 574                if (evsel == NULL) {
 575                        pr_debug("event with id %" PRIu64
 576                                 " doesn't map to an evsel\n", sample.id);
 577                        goto out_munmap;
 578                }
 579                nr_events[evsel->idx]++;
 580        }
 581
 582        list_for_each_entry(evsel, &evlist->entries, node) {
 583                if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
 584                        pr_debug("expected %d %s events, got %d\n",
 585                                 expected_nr_events[evsel->idx],
 586                                 event_name(evsel), nr_events[evsel->idx]);
 587                        goto out_munmap;
 588                }
 589        }
 590
 591        err = 0;
 592out_munmap:
 593        perf_evlist__munmap(evlist);
 594out_close_fd:
 595        for (i = 0; i < nsyscalls; ++i)
 596                perf_evsel__close_fd(evsels[i], 1, threads->nr);
 597out_free_evlist:
 598        perf_evlist__delete(evlist);
 599out_free_cpus:
 600        cpu_map__delete(cpus);
 601out_free_threads:
 602        thread_map__delete(threads);
 603        return err;
 604#undef nsyscalls
 605}
 606
 607#define TEST_ASSERT_VAL(text, cond) \
 608do { \
 609        if (!(cond)) { \
 610                pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
 611                return -1; \
 612        } \
 613} while (0)
 614
 615static int test__checkevent_tracepoint(struct perf_evlist *evlist)
 616{
 617        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 618                                              struct perf_evsel, node);
 619
 620        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 621        TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
 622        TEST_ASSERT_VAL("wrong sample_type",
 623                (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
 624                evsel->attr.sample_type);
 625        TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
 626        return 0;
 627}
 628
 629static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
 630{
 631        struct perf_evsel *evsel;
 632
 633        TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
 634
 635        list_for_each_entry(evsel, &evlist->entries, node) {
 636                TEST_ASSERT_VAL("wrong type",
 637                        PERF_TYPE_TRACEPOINT == evsel->attr.type);
 638                TEST_ASSERT_VAL("wrong sample_type",
 639                        (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
 640                        == evsel->attr.sample_type);
 641                TEST_ASSERT_VAL("wrong sample_period",
 642                        1 == evsel->attr.sample_period);
 643        }
 644        return 0;
 645}
 646
 647static int test__checkevent_raw(struct perf_evlist *evlist)
 648{
 649        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 650                                              struct perf_evsel, node);
 651
 652        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 653        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
 654        TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config);
 655        return 0;
 656}
 657
 658static int test__checkevent_numeric(struct perf_evlist *evlist)
 659{
 660        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 661                                              struct perf_evsel, node);
 662
 663        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 664        TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
 665        TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
 666        return 0;
 667}
 668
 669static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
 670{
 671        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 672                                              struct perf_evsel, node);
 673
 674        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 675        TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
 676        TEST_ASSERT_VAL("wrong config",
 677                        PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
 678        return 0;
 679}
 680
 681static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
 682{
 683        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 684                                              struct perf_evsel, node);
 685
 686        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 687        TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
 688        TEST_ASSERT_VAL("wrong config",
 689                        PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
 690        TEST_ASSERT_VAL("wrong period",
 691                        100000 == evsel->attr.sample_period);
 692        TEST_ASSERT_VAL("wrong config1",
 693                        0 == evsel->attr.config1);
 694        TEST_ASSERT_VAL("wrong config2",
 695                        1 == evsel->attr.config2);
 696        return 0;
 697}
 698
 699static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
 700{
 701        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 702                                              struct perf_evsel, node);
 703
 704        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 705        TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
 706        TEST_ASSERT_VAL("wrong config",
 707                        PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
 708        return 0;
 709}
 710
 711static int test__checkevent_genhw(struct perf_evlist *evlist)
 712{
 713        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 714                                              struct perf_evsel, node);
 715
 716        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 717        TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
 718        TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config);
 719        return 0;
 720}
 721
 722static int test__checkevent_breakpoint(struct perf_evlist *evlist)
 723{
 724        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 725                                              struct perf_evsel, node);
 726
 727        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 728        TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
 729        TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
 730        TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
 731                                         evsel->attr.bp_type);
 732        TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 ==
 733                                        evsel->attr.bp_len);
 734        return 0;
 735}
 736
 737static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
 738{
 739        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 740                                              struct perf_evsel, node);
 741
 742        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 743        TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
 744        TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
 745        TEST_ASSERT_VAL("wrong bp_type",
 746                        HW_BREAKPOINT_X == evsel->attr.bp_type);
 747        TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len);
 748        return 0;
 749}
 750
 751static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
 752{
 753        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 754                                              struct perf_evsel, node);
 755
 756        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 757        TEST_ASSERT_VAL("wrong type",
 758                        PERF_TYPE_BREAKPOINT == evsel->attr.type);
 759        TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
 760        TEST_ASSERT_VAL("wrong bp_type",
 761                        HW_BREAKPOINT_R == evsel->attr.bp_type);
 762        TEST_ASSERT_VAL("wrong bp_len",
 763                        HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
 764        return 0;
 765}
 766
 767static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
 768{
 769        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 770                                              struct perf_evsel, node);
 771
 772        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 773        TEST_ASSERT_VAL("wrong type",
 774                        PERF_TYPE_BREAKPOINT == evsel->attr.type);
 775        TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
 776        TEST_ASSERT_VAL("wrong bp_type",
 777                        HW_BREAKPOINT_W == evsel->attr.bp_type);
 778        TEST_ASSERT_VAL("wrong bp_len",
 779                        HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
 780        return 0;
 781}
 782
 783static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
 784{
 785        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 786                                              struct perf_evsel, node);
 787
 788        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 789        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
 790        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 791        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 792
 793        return test__checkevent_tracepoint(evlist);
 794}
 795
 796static int
 797test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
 798{
 799        struct perf_evsel *evsel;
 800
 801        TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
 802
 803        list_for_each_entry(evsel, &evlist->entries, node) {
 804                TEST_ASSERT_VAL("wrong exclude_user",
 805                                !evsel->attr.exclude_user);
 806                TEST_ASSERT_VAL("wrong exclude_kernel",
 807                                evsel->attr.exclude_kernel);
 808                TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 809                TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 810        }
 811
 812        return test__checkevent_tracepoint_multi(evlist);
 813}
 814
 815static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
 816{
 817        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 818                                              struct perf_evsel, node);
 819
 820        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 821        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
 822        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 823        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 824
 825        return test__checkevent_raw(evlist);
 826}
 827
 828static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
 829{
 830        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 831                                              struct perf_evsel, node);
 832
 833        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 834        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 835        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
 836        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 837
 838        return test__checkevent_numeric(evlist);
 839}
 840
 841static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
 842{
 843        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 844                                              struct perf_evsel, node);
 845
 846        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 847        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 848        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
 849        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 850
 851        return test__checkevent_symbolic_name(evlist);
 852}
 853
 854static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
 855{
 856        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 857                                              struct perf_evsel, node);
 858
 859        TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
 860        TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
 861
 862        return test__checkevent_symbolic_name(evlist);
 863}
 864
 865static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
 866{
 867        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 868                                              struct perf_evsel, node);
 869
 870        TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
 871        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
 872
 873        return test__checkevent_symbolic_name(evlist);
 874}
 875
 876static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
 877{
 878        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 879                                              struct perf_evsel, node);
 880
 881        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
 882        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 883        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 884        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 885
 886        return test__checkevent_symbolic_alias(evlist);
 887}
 888
 889static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
 890{
 891        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 892                                              struct perf_evsel, node);
 893
 894        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 895        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
 896        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 897        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 898
 899        return test__checkevent_genhw(evlist);
 900}
 901
 902static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
 903{
 904        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 905                                              struct perf_evsel, node);
 906
 907        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
 908        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 909        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 910        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 911
 912        return test__checkevent_breakpoint(evlist);
 913}
 914
 915static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
 916{
 917        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 918                                              struct perf_evsel, node);
 919
 920        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 921        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
 922        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 923        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 924
 925        return test__checkevent_breakpoint_x(evlist);
 926}
 927
 928static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
 929{
 930        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 931                                              struct perf_evsel, node);
 932
 933        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 934        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 935        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
 936        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 937
 938        return test__checkevent_breakpoint_r(evlist);
 939}
 940
 941static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
 942{
 943        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 944                                              struct perf_evsel, node);
 945
 946        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
 947        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 948        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 949        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 950
 951        return test__checkevent_breakpoint_w(evlist);
 952}
 953
 954static int test__checkevent_pmu(struct perf_evlist *evlist)
 955{
 956
 957        struct perf_evsel *evsel = list_entry(evlist->entries.next,
 958                                              struct perf_evsel, node);
 959
 960        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
 961        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
 962        TEST_ASSERT_VAL("wrong config",    10 == evsel->attr.config);
 963        TEST_ASSERT_VAL("wrong config1",    1 == evsel->attr.config1);
 964        TEST_ASSERT_VAL("wrong config2",    3 == evsel->attr.config2);
 965        TEST_ASSERT_VAL("wrong period",  1000 == evsel->attr.sample_period);
 966
 967        return 0;
 968}
 969
 970static int test__checkevent_list(struct perf_evlist *evlist)
 971{
 972        struct perf_evsel *evsel;
 973
 974        TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
 975
 976        /* r1 */
 977        evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
 978        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
 979        TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
 980        TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
 981        TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2);
 982        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
 983        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
 984        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
 985        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 986
 987        /* syscalls:sys_enter_open:k */
 988        evsel = list_entry(evsel->node.next, struct perf_evsel, node);
 989        TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
 990        TEST_ASSERT_VAL("wrong sample_type",
 991                (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
 992                evsel->attr.sample_type);
 993        TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
 994        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
 995        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
 996        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 997        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 998
 999        /* 1:1:hp */
1000        evsel = list_entry(evsel->node.next, struct perf_evsel, node);
1001        TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
1002        TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
1003        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
1004        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
1005        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
1006        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
1007
1008        return 0;
1009}
1010
1011static struct test__event_st {
1012        const char *name;
1013        __u32 type;
1014        int (*check)(struct perf_evlist *evlist);
1015} test__events[] = {
1016        {
1017                .name  = "syscalls:sys_enter_open",
1018                .check = test__checkevent_tracepoint,
1019        },
1020        {
1021                .name  = "syscalls:*",
1022                .check = test__checkevent_tracepoint_multi,
1023        },
1024        {
1025                .name  = "r1a",
1026                .check = test__checkevent_raw,
1027        },
1028        {
1029                .name  = "1:1",
1030                .check = test__checkevent_numeric,
1031        },
1032        {
1033                .name  = "instructions",
1034                .check = test__checkevent_symbolic_name,
1035        },
1036        {
1037                .name  = "cycles/period=100000,config2/",
1038                .check = test__checkevent_symbolic_name_config,
1039        },
1040        {
1041                .name  = "faults",
1042                .check = test__checkevent_symbolic_alias,
1043        },
1044        {
1045                .name  = "L1-dcache-load-miss",
1046                .check = test__checkevent_genhw,
1047        },
1048        {
1049                .name  = "mem:0",
1050                .check = test__checkevent_breakpoint,
1051        },
1052        {
1053                .name  = "mem:0:x",
1054                .check = test__checkevent_breakpoint_x,
1055        },
1056        {
1057                .name  = "mem:0:r",
1058                .check = test__checkevent_breakpoint_r,
1059        },
1060        {
1061                .name  = "mem:0:w",
1062                .check = test__checkevent_breakpoint_w,
1063        },
1064        {
1065                .name  = "syscalls:sys_enter_open:k",
1066                .check = test__checkevent_tracepoint_modifier,
1067        },
1068        {
1069                .name  = "syscalls:*:u",
1070                .check = test__checkevent_tracepoint_multi_modifier,
1071        },
1072        {
1073                .name  = "r1a:kp",
1074                .check = test__checkevent_raw_modifier,
1075        },
1076        {
1077                .name  = "1:1:hp",
1078                .check = test__checkevent_numeric_modifier,
1079        },
1080        {
1081                .name  = "instructions:h",
1082                .check = test__checkevent_symbolic_name_modifier,
1083        },
1084        {
1085                .name  = "faults:u",
1086                .check = test__checkevent_symbolic_alias_modifier,
1087        },
1088        {
1089                .name  = "L1-dcache-load-miss:kp",
1090                .check = test__checkevent_genhw_modifier,
1091        },
1092        {
1093                .name  = "mem:0:u",
1094                .check = test__checkevent_breakpoint_modifier,
1095        },
1096        {
1097                .name  = "mem:0:x:k",
1098                .check = test__checkevent_breakpoint_x_modifier,
1099        },
1100        {
1101                .name  = "mem:0:r:hp",
1102                .check = test__checkevent_breakpoint_r_modifier,
1103        },
1104        {
1105                .name  = "mem:0:w:up",
1106                .check = test__checkevent_breakpoint_w_modifier,
1107        },
1108        {
1109                .name  = "cpu/config=10,config1,config2=3,period=1000/u",
1110                .check = test__checkevent_pmu,
1111        },
1112        {
1113                .name  = "r1,syscalls:sys_enter_open:k,1:1:hp",
1114                .check = test__checkevent_list,
1115        },
1116        {
1117                .name  = "instructions:G",
1118                .check = test__checkevent_exclude_host_modifier,
1119        },
1120        {
1121                .name  = "instructions:H",
1122                .check = test__checkevent_exclude_guest_modifier,
1123        },
1124};
1125
1126#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
1127
1128static int test__parse_events(void)
1129{
1130        struct perf_evlist *evlist;
1131        u_int i;
1132        int ret = 0;
1133
1134        for (i = 0; i < TEST__EVENTS_CNT; i++) {
1135                struct test__event_st *e = &test__events[i];
1136
1137                evlist = perf_evlist__new(NULL, NULL);
1138                if (evlist == NULL)
1139                        break;
1140
1141                ret = parse_events(evlist, e->name, 0);
1142                if (ret) {
1143                        pr_debug("failed to parse event '%s', err %d\n",
1144                                 e->name, ret);
1145                        break;
1146                }
1147
1148                ret = e->check(evlist);
1149                perf_evlist__delete(evlist);
1150                if (ret)
1151                        break;
1152        }
1153
1154        return ret;
1155}
1156
1157static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp,
1158                                         size_t *sizep)
1159{
1160        cpu_set_t *mask;
1161        size_t size;
1162        int i, cpu = -1, nrcpus = 1024;
1163realloc:
1164        mask = CPU_ALLOC(nrcpus);
1165        size = CPU_ALLOC_SIZE(nrcpus);
1166        CPU_ZERO_S(size, mask);
1167
1168        if (sched_getaffinity(pid, size, mask) == -1) {
1169                CPU_FREE(mask);
1170                if (errno == EINVAL && nrcpus < (1024 << 8)) {
1171                        nrcpus = nrcpus << 2;
1172                        goto realloc;
1173                }
1174                perror("sched_getaffinity");
1175                        return -1;
1176        }
1177
1178        for (i = 0; i < nrcpus; i++) {
1179                if (CPU_ISSET_S(i, size, mask)) {
1180                        if (cpu == -1) {
1181                                cpu = i;
1182                                *maskp = mask;
1183                                *sizep = size;
1184                        } else
1185                                CPU_CLR_S(i, size, mask);
1186                }
1187        }
1188
1189        if (cpu == -1)
1190                CPU_FREE(mask);
1191
1192        return cpu;
1193}
1194
1195static int test__PERF_RECORD(void)
1196{
1197        struct perf_record_opts opts = {
1198                .no_delay   = true,
1199                .freq       = 10,
1200                .mmap_pages = 256,
1201        };
1202        cpu_set_t *cpu_mask = NULL;
1203        size_t cpu_mask_size = 0;
1204        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1205        struct perf_evsel *evsel;
1206        struct perf_sample sample;
1207        const char *cmd = "sleep";
1208        const char *argv[] = { cmd, "1", NULL, };
1209        char *bname;
1210        u64 sample_type, prev_time = 0;
1211        bool found_cmd_mmap = false,
1212             found_libc_mmap = false,
1213             found_vdso_mmap = false,
1214             found_ld_mmap = false;
1215        int err = -1, errs = 0, i, wakeups = 0, sample_size;
1216        u32 cpu;
1217        int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
1218
1219        if (evlist == NULL || argv == NULL) {
1220                pr_debug("Not enough memory to create evlist\n");
1221                goto out;
1222        }
1223
1224        /*
1225         * We need at least one evsel in the evlist, use the default
1226         * one: "cycles".
1227         */
1228        err = perf_evlist__add_default(evlist);
1229        if (err < 0) {
1230                pr_debug("Not enough memory to create evsel\n");
1231                goto out_delete_evlist;
1232        }
1233
1234        /*
1235         * Create maps of threads and cpus to monitor. In this case
1236         * we start with all threads and cpus (-1, -1) but then in
1237         * perf_evlist__prepare_workload we'll fill in the only thread
1238         * we're monitoring, the one forked there.
1239         */
1240        err = perf_evlist__create_maps(evlist, opts.target_pid,
1241                                       opts.target_tid, UINT_MAX, opts.cpu_list);
1242        if (err < 0) {
1243                pr_debug("Not enough memory to create thread/cpu maps\n");
1244                goto out_delete_evlist;
1245        }
1246
1247        /*
1248         * Prepare the workload in argv[] to run, it'll fork it, and then wait
1249         * for perf_evlist__start_workload() to exec it. This is done this way
1250         * so that we have time to open the evlist (calling sys_perf_event_open
1251         * on all the fds) and then mmap them.
1252         */
1253        err = perf_evlist__prepare_workload(evlist, &opts, argv);
1254        if (err < 0) {
1255                pr_debug("Couldn't run the workload!\n");
1256                goto out_delete_evlist;
1257        }
1258
1259        /*
1260         * Config the evsels, setting attr->comm on the first one, etc.
1261         */
1262        evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
1263        evsel->attr.sample_type |= PERF_SAMPLE_CPU;
1264        evsel->attr.sample_type |= PERF_SAMPLE_TID;
1265        evsel->attr.sample_type |= PERF_SAMPLE_TIME;
1266        perf_evlist__config_attrs(evlist, &opts);
1267
1268        err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask,
1269                                            &cpu_mask_size);
1270        if (err < 0) {
1271                pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
1272                goto out_delete_evlist;
1273        }
1274
1275        cpu = err;
1276
1277        /*
1278         * So that we can check perf_sample.cpu on all the samples.
1279         */
1280        if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) {
1281                pr_debug("sched_setaffinity: %s\n", strerror(errno));
1282                goto out_free_cpu_mask;
1283        }
1284
1285        /*
1286         * Call sys_perf_event_open on all the fds on all the evsels,
1287         * grouping them if asked to.
1288         */
1289        err = perf_evlist__open(evlist, opts.group);
1290        if (err < 0) {
1291                pr_debug("perf_evlist__open: %s\n", strerror(errno));
1292                goto out_delete_evlist;
1293        }
1294
1295        /*
1296         * mmap the first fd on a given CPU and ask for events for the other
1297         * fds in the same CPU to be injected in the same mmap ring buffer
1298         * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)).
1299         */
1300        err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
1301        if (err < 0) {
1302                pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
1303                goto out_delete_evlist;
1304        }
1305
1306        /*
1307         * We'll need these two to parse the PERF_SAMPLE_* fields in each
1308         * event.
1309         */
1310        sample_type = perf_evlist__sample_type(evlist);
1311        sample_size = __perf_evsel__sample_size(sample_type);
1312
1313        /*
1314         * Now that all is properly set up, enable the events, they will
1315         * count just on workload.pid, which will start...
1316         */
1317        perf_evlist__enable(evlist);
1318
1319        /*
1320         * Now!
1321         */
1322        perf_evlist__start_workload(evlist);
1323
1324        while (1) {
1325                int before = total_events;
1326
1327                for (i = 0; i < evlist->nr_mmaps; i++) {
1328                        union perf_event *event;
1329
1330                        while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1331                                const u32 type = event->header.type;
1332                                const char *name = perf_event__name(type);
1333
1334                                ++total_events;
1335                                if (type < PERF_RECORD_MAX)
1336                                        nr_events[type]++;
1337
1338                                err = perf_event__parse_sample(event, sample_type,
1339                                                               sample_size, true,
1340                                                               &sample, false);
1341                                if (err < 0) {
1342                                        if (verbose)
1343                                                perf_event__fprintf(event, stderr);
1344                                        pr_debug("Couldn't parse sample\n");
1345                                        goto out_err;
1346                                }
1347
1348                                if (verbose) {
1349                                        pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
1350                                        perf_event__fprintf(event, stderr);
1351                                }
1352
1353                                if (prev_time > sample.time) {
1354                                        pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n",
1355                                                 name, prev_time, sample.time);
1356                                        ++errs;
1357                                }
1358
1359                                prev_time = sample.time;
1360
1361                                if (sample.cpu != cpu) {
1362                                        pr_debug("%s with unexpected cpu, expected %d, got %d\n",
1363                                                 name, cpu, sample.cpu);
1364                                        ++errs;
1365                                }
1366
1367                                if ((pid_t)sample.pid != evlist->workload.pid) {
1368                                        pr_debug("%s with unexpected pid, expected %d, got %d\n",
1369                                                 name, evlist->workload.pid, sample.pid);
1370                                        ++errs;
1371                                }
1372
1373                                if ((pid_t)sample.tid != evlist->workload.pid) {
1374                                        pr_debug("%s with unexpected tid, expected %d, got %d\n",
1375                                                 name, evlist->workload.pid, sample.tid);
1376                                        ++errs;
1377                                }
1378
1379                                if ((type == PERF_RECORD_COMM ||
1380                                     type == PERF_RECORD_MMAP ||
1381                                     type == PERF_RECORD_FORK ||
1382                                     type == PERF_RECORD_EXIT) &&
1383                                     (pid_t)event->comm.pid != evlist->workload.pid) {
1384                                        pr_debug("%s with unexpected pid/tid\n", name);
1385                                        ++errs;
1386                                }
1387
1388                                if ((type == PERF_RECORD_COMM ||
1389                                     type == PERF_RECORD_MMAP) &&
1390                                     event->comm.pid != event->comm.tid) {
1391                                        pr_debug("%s with different pid/tid!\n", name);
1392                                        ++errs;
1393                                }
1394
1395                                switch (type) {
1396                                case PERF_RECORD_COMM:
1397                                        if (strcmp(event->comm.comm, cmd)) {
1398                                                pr_debug("%s with unexpected comm!\n", name);
1399                                                ++errs;
1400                                        }
1401                                        break;
1402                                case PERF_RECORD_EXIT:
1403                                        goto found_exit;
1404                                case PERF_RECORD_MMAP:
1405                                        bname = strrchr(event->mmap.filename, '/');
1406                                        if (bname != NULL) {
1407                                                if (!found_cmd_mmap)
1408                                                        found_cmd_mmap = !strcmp(bname + 1, cmd);
1409                                                if (!found_libc_mmap)
1410                                                        found_libc_mmap = !strncmp(bname + 1, "libc", 4);
1411                                                if (!found_ld_mmap)
1412                                                        found_ld_mmap = !strncmp(bname + 1, "ld", 2);
1413                                        } else if (!found_vdso_mmap)
1414                                                found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
1415                                        break;
1416
1417                                case PERF_RECORD_SAMPLE:
1418                                        /* Just ignore samples for now */
1419                                        break;
1420                                default:
1421                                        pr_debug("Unexpected perf_event->header.type %d!\n",
1422                                                 type);
1423                                        ++errs;
1424                                }
1425                        }
1426                }
1427
1428                /*
1429                 * We don't use poll here because at least at 3.1 times the
1430                 * PERF_RECORD_{!SAMPLE} events don't honour
1431                 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
1432                 */
1433                if (total_events == before && false)
1434                        poll(evlist->pollfd, evlist->nr_fds, -1);
1435
1436                sleep(1);
1437                if (++wakeups > 5) {
1438                        pr_debug("No PERF_RECORD_EXIT event!\n");
1439                        break;
1440                }
1441        }
1442
1443found_exit:
1444        if (nr_events[PERF_RECORD_COMM] > 1) {
1445                pr_debug("Excessive number of PERF_RECORD_COMM events!\n");
1446                ++errs;
1447        }
1448
1449        if (nr_events[PERF_RECORD_COMM] == 0) {
1450                pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd);
1451                ++errs;
1452        }
1453
1454        if (!found_cmd_mmap) {
1455                pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd);
1456                ++errs;
1457        }
1458
1459        if (!found_libc_mmap) {
1460                pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc");
1461                ++errs;
1462        }
1463
1464        if (!found_ld_mmap) {
1465                pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld");
1466                ++errs;
1467        }
1468
1469        if (!found_vdso_mmap) {
1470                pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
1471                ++errs;
1472        }
1473out_err:
1474        perf_evlist__munmap(evlist);
1475out_free_cpu_mask:
1476        CPU_FREE(cpu_mask);
1477out_delete_evlist:
1478        perf_evlist__delete(evlist);
1479out:
1480        return (err < 0 || errs > 0) ? -1 : 0;
1481}
1482
1483
1484#if defined(__x86_64__) || defined(__i386__)
1485
1486#define barrier() asm volatile("" ::: "memory")
1487
1488static u64 rdpmc(unsigned int counter)
1489{
1490        unsigned int low, high;
1491
1492        asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
1493
1494        return low | ((u64)high) << 32;
1495}
1496
1497static u64 rdtsc(void)
1498{
1499        unsigned int low, high;
1500
1501        asm volatile("rdtsc" : "=a" (low), "=d" (high));
1502
1503        return low | ((u64)high) << 32;
1504}
1505
1506static u64 mmap_read_self(void *addr)
1507{
1508        struct perf_event_mmap_page *pc = addr;
1509        u32 seq, idx, time_mult = 0, time_shift = 0;
1510        u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
1511
1512        do {
1513                seq = pc->lock;
1514                barrier();
1515
1516                enabled = pc->time_enabled;
1517                running = pc->time_running;
1518
1519                if (enabled != running) {
1520                        cyc = rdtsc();
1521                        time_mult = pc->time_mult;
1522                        time_shift = pc->time_shift;
1523                        time_offset = pc->time_offset;
1524                }
1525
1526                idx = pc->index;
1527                count = pc->offset;
1528                if (idx)
1529                        count += rdpmc(idx - 1);
1530
1531                barrier();
1532        } while (pc->lock != seq);
1533
1534        if (enabled != running) {
1535                u64 quot, rem;
1536
1537                quot = (cyc >> time_shift);
1538                rem = cyc & ((1 << time_shift) - 1);
1539                delta = time_offset + quot * time_mult +
1540                        ((rem * time_mult) >> time_shift);
1541
1542                enabled += delta;
1543                if (idx)
1544                        running += delta;
1545
1546                quot = count / running;
1547                rem = count % running;
1548                count = quot * enabled + (rem * enabled) / running;
1549        }
1550
1551        return count;
1552}
1553
1554/*
1555 * If the RDPMC instruction faults then signal this back to the test parent task:
1556 */
1557static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used)
1558{
1559        exit(-1);
1560}
1561
1562static int __test__rdpmc(void)
1563{
1564        long page_size = sysconf(_SC_PAGE_SIZE);
1565        volatile int tmp = 0;
1566        u64 i, loops = 1000;
1567        int n;
1568        int fd;
1569        void *addr;
1570        struct perf_event_attr attr = {
1571                .type = PERF_TYPE_HARDWARE,
1572                .config = PERF_COUNT_HW_INSTRUCTIONS,
1573                .exclude_kernel = 1,
1574        };
1575        u64 delta_sum = 0;
1576        struct sigaction sa;
1577
1578        sigfillset(&sa.sa_mask);
1579        sa.sa_sigaction = segfault_handler;
1580        sigaction(SIGSEGV, &sa, NULL);
1581
1582        fprintf(stderr, "\n\n");
1583
1584        fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1585        if (fd < 0) {
1586                die("Error: sys_perf_event_open() syscall returned "
1587                    "with %d (%s)\n", fd, strerror(errno));
1588        }
1589
1590        addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
1591        if (addr == (void *)(-1)) {
1592                die("Error: mmap() syscall returned "
1593                    "with (%s)\n", strerror(errno));
1594        }
1595
1596        for (n = 0; n < 6; n++) {
1597                u64 stamp, now, delta;
1598
1599                stamp = mmap_read_self(addr);
1600
1601                for (i = 0; i < loops; i++)
1602                        tmp++;
1603
1604                now = mmap_read_self(addr);
1605                loops *= 10;
1606
1607                delta = now - stamp;
1608                fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta);
1609
1610                delta_sum += delta;
1611        }
1612
1613        munmap(addr, page_size);
1614        close(fd);
1615
1616        fprintf(stderr, "   ");
1617
1618        if (!delta_sum)
1619                return -1;
1620
1621        return 0;
1622}
1623
1624static int test__rdpmc(void)
1625{
1626        int status = 0;
1627        int wret = 0;
1628        int ret;
1629        int pid;
1630
1631        pid = fork();
1632        if (pid < 0)
1633                return -1;
1634
1635        if (!pid) {
1636                ret = __test__rdpmc();
1637
1638                exit(ret);
1639        }
1640
1641        wret = waitpid(pid, &status, 0);
1642        if (wret < 0 || status)
1643                return -1;
1644
1645        return 0;
1646}
1647
1648#endif
1649
1650static int test__perf_pmu(void)
1651{
1652        return perf_pmu__test();
1653}
1654
1655static struct test {
1656        const char *desc;
1657        int (*func)(void);
1658} tests[] = {
1659        {
1660                .desc = "vmlinux symtab matches kallsyms",
1661                .func = test__vmlinux_matches_kallsyms,
1662        },
1663        {
1664                .desc = "detect open syscall event",
1665                .func = test__open_syscall_event,
1666        },
1667        {
1668                .desc = "detect open syscall event on all cpus",
1669                .func = test__open_syscall_event_on_all_cpus,
1670        },
1671        {
1672                .desc = "read samples using the mmap interface",
1673                .func = test__basic_mmap,
1674        },
1675        {
1676                .desc = "parse events tests",
1677                .func = test__parse_events,
1678        },
1679#if defined(__x86_64__) || defined(__i386__)
1680        {
1681                .desc = "x86 rdpmc test",
1682                .func = test__rdpmc,
1683        },
1684#endif
1685        {
1686                .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1687                .func = test__PERF_RECORD,
1688        },
1689        {
1690                .desc = "Test perf pmu format parsing",
1691                .func = test__perf_pmu,
1692        },
1693        {
1694                .func = NULL,
1695        },
1696};
1697
1698static bool perf_test__matches(int curr, int argc, const char *argv[])
1699{
1700        int i;
1701
1702        if (argc == 0)
1703                return true;
1704
1705        for (i = 0; i < argc; ++i) {
1706                char *end;
1707                long nr = strtoul(argv[i], &end, 10);
1708
1709                if (*end == '\0') {
1710                        if (nr == curr + 1)
1711                                return true;
1712                        continue;
1713                }
1714
1715                if (strstr(tests[curr].desc, argv[i]))
1716                        return true;
1717        }
1718
1719        return false;
1720}
1721
1722static int __cmd_test(int argc, const char *argv[])
1723{
1724        int i = 0;
1725
1726        while (tests[i].func) {
1727                int curr = i++, err;
1728
1729                if (!perf_test__matches(curr, argc, argv))
1730                        continue;
1731
1732                pr_info("%2d: %s:", i, tests[curr].desc);
1733                pr_debug("\n--- start ---\n");
1734                err = tests[curr].func();
1735                pr_debug("---- end ----\n%s:", tests[curr].desc);
1736                pr_info(" %s\n", err ? "FAILED!\n" : "Ok");
1737        }
1738
1739        return 0;
1740}
1741
1742static int perf_test__list(int argc, const char **argv)
1743{
1744        int i = 0;
1745
1746        while (tests[i].func) {
1747                int curr = i++;
1748
1749                if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
1750                        continue;
1751
1752                pr_info("%2d: %s\n", i, tests[curr].desc);
1753        }
1754
1755        return 0;
1756}
1757
1758int cmd_test(int argc, const char **argv, const char *prefix __used)
1759{
1760        const char * const test_usage[] = {
1761        "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
1762        NULL,
1763        };
1764        const struct option test_options[] = {
1765        OPT_INCR('v', "verbose", &verbose,
1766                    "be more verbose (show symbol address, etc)"),
1767        OPT_END()
1768        };
1769
1770        argc = parse_options(argc, argv, test_options, test_usage, 0);
1771        if (argc >= 1 && !strcmp(argv[0], "list"))
1772                return perf_test__list(argc, argv);
1773
1774        symbol_conf.priv_size = sizeof(int);
1775        symbol_conf.sort_by_name = true;
1776        symbol_conf.try_vmlinux_path = true;
1777
1778        if (symbol__init() < 0)
1779                return -1;
1780
1781        return __cmd_test(argc, argv);
1782}
1783