linux/tools/perf/util/parse-events.c
<<
>>
Prefs
   1#include "../../../include/linux/hw_breakpoint.h"
   2#include "util.h"
   3#include "../perf.h"
   4#include "parse-options.h"
   5#include "parse-events.h"
   6#include "exec_cmd.h"
   7#include "string.h"
   8#include "symbol.h"
   9#include "cache.h"
  10#include "header.h"
  11#include "debugfs.h"
  12
  13int                             nr_counters;
  14
  15struct perf_event_attr          attrs[MAX_COUNTERS];
  16char                            *filters[MAX_COUNTERS];
  17
  18struct event_symbol {
  19        u8              type;
  20        u64             config;
  21        const char      *symbol;
  22        const char      *alias;
  23};
  24
  25enum event_result {
  26        EVT_FAILED,
  27        EVT_HANDLED,
  28        EVT_HANDLED_ALL
  29};
  30
  31char debugfs_path[MAXPATHLEN];
  32
  33#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
  34#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
  35
  36static struct event_symbol event_symbols[] = {
  37  { CHW(CPU_CYCLES),            "cpu-cycles",           "cycles"        },
  38  { CHW(INSTRUCTIONS),          "instructions",         ""              },
  39  { CHW(CACHE_REFERENCES),      "cache-references",     ""              },
  40  { CHW(CACHE_MISSES),          "cache-misses",         ""              },
  41  { CHW(BRANCH_INSTRUCTIONS),   "branch-instructions",  "branches"      },
  42  { CHW(BRANCH_MISSES),         "branch-misses",        ""              },
  43  { CHW(BUS_CYCLES),            "bus-cycles",           ""              },
  44
  45  { CSW(CPU_CLOCK),             "cpu-clock",            ""              },
  46  { CSW(TASK_CLOCK),            "task-clock",           ""              },
  47  { CSW(PAGE_FAULTS),           "page-faults",          "faults"        },
  48  { CSW(PAGE_FAULTS_MIN),       "minor-faults",         ""              },
  49  { CSW(PAGE_FAULTS_MAJ),       "major-faults",         ""              },
  50  { CSW(CONTEXT_SWITCHES),      "context-switches",     "cs"            },
  51  { CSW(CPU_MIGRATIONS),        "cpu-migrations",       "migrations"    },
  52  { CSW(ALIGNMENT_FAULTS),      "alignment-faults",     ""              },
  53  { CSW(EMULATION_FAULTS),      "emulation-faults",     ""              },
  54};
  55
  56#define __PERF_EVENT_FIELD(config, name) \
  57        ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
  58
  59#define PERF_EVENT_RAW(config)  __PERF_EVENT_FIELD(config, RAW)
  60#define PERF_EVENT_CONFIG(config)       __PERF_EVENT_FIELD(config, CONFIG)
  61#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
  62#define PERF_EVENT_ID(config)           __PERF_EVENT_FIELD(config, EVENT)
  63
  64static const char *hw_event_names[] = {
  65        "cycles",
  66        "instructions",
  67        "cache-references",
  68        "cache-misses",
  69        "branches",
  70        "branch-misses",
  71        "bus-cycles",
  72};
  73
  74static const char *sw_event_names[] = {
  75        "cpu-clock-msecs",
  76        "task-clock-msecs",
  77        "page-faults",
  78        "context-switches",
  79        "CPU-migrations",
  80        "minor-faults",
  81        "major-faults",
  82        "alignment-faults",
  83        "emulation-faults",
  84};
  85
  86#define MAX_ALIASES 8
  87
  88static const char *hw_cache[][MAX_ALIASES] = {
  89 { "L1-dcache", "l1-d",         "l1d",          "L1-data",              },
  90 { "L1-icache", "l1-i",         "l1i",          "L1-instruction",       },
  91 { "LLC",       "L2"                                                    },
  92 { "dTLB",      "d-tlb",        "Data-TLB",                             },
  93 { "iTLB",      "i-tlb",        "Instruction-TLB",                      },
  94 { "branch",    "branches",     "bpu",          "btb",          "bpc",  },
  95};
  96
  97static const char *hw_cache_op[][MAX_ALIASES] = {
  98 { "load",      "loads",        "read",                                 },
  99 { "store",     "stores",       "write",                                },
 100 { "prefetch",  "prefetches",   "speculative-read", "speculative-load", },
 101};
 102
 103static const char *hw_cache_result[][MAX_ALIASES] = {
 104 { "refs",      "Reference",    "ops",          "access",               },
 105 { "misses",    "miss",                                                 },
 106};
 107
 108#define C(x)            PERF_COUNT_HW_CACHE_##x
 109#define CACHE_READ      (1 << C(OP_READ))
 110#define CACHE_WRITE     (1 << C(OP_WRITE))
 111#define CACHE_PREFETCH  (1 << C(OP_PREFETCH))
 112#define COP(x)          (1 << x)
 113
 114/*
 115 * cache operartion stat
 116 * L1I : Read and prefetch only
 117 * ITLB and BPU : Read-only
 118 */
 119static unsigned long hw_cache_stat[C(MAX)] = {
 120 [C(L1D)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 121 [C(L1I)]       = (CACHE_READ | CACHE_PREFETCH),
 122 [C(LL)]        = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 123 [C(DTLB)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 124 [C(ITLB)]      = (CACHE_READ),
 125 [C(BPU)]       = (CACHE_READ),
 126};
 127
 128#define for_each_subsystem(sys_dir, sys_dirent, sys_next)              \
 129        while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
 130        if (sys_dirent.d_type == DT_DIR &&                                     \
 131           (strcmp(sys_dirent.d_name, ".")) &&                                 \
 132           (strcmp(sys_dirent.d_name, "..")))
 133
 134static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
 135{
 136        char evt_path[MAXPATHLEN];
 137        int fd;
 138
 139        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
 140                        sys_dir->d_name, evt_dir->d_name);
 141        fd = open(evt_path, O_RDONLY);
 142        if (fd < 0)
 143                return -EINVAL;
 144        close(fd);
 145
 146        return 0;
 147}
 148
 149#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)              \
 150        while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
 151        if (evt_dirent.d_type == DT_DIR &&                                     \
 152           (strcmp(evt_dirent.d_name, ".")) &&                                 \
 153           (strcmp(evt_dirent.d_name, "..")) &&                                \
 154           (!tp_event_has_id(&sys_dirent, &evt_dirent)))
 155
 156#define MAX_EVENT_LENGTH 512
 157
 158
 159struct tracepoint_path *tracepoint_id_to_path(u64 config)
 160{
 161        struct tracepoint_path *path = NULL;
 162        DIR *sys_dir, *evt_dir;
 163        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 164        char id_buf[4];
 165        int fd;
 166        u64 id;
 167        char evt_path[MAXPATHLEN];
 168        char dir_path[MAXPATHLEN];
 169
 170        if (debugfs_valid_mountpoint(debugfs_path))
 171                return NULL;
 172
 173        sys_dir = opendir(debugfs_path);
 174        if (!sys_dir)
 175                return NULL;
 176
 177        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 178
 179                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 180                         sys_dirent.d_name);
 181                evt_dir = opendir(dir_path);
 182                if (!evt_dir)
 183                        continue;
 184
 185                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 186
 187                        snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
 188                                 evt_dirent.d_name);
 189                        fd = open(evt_path, O_RDONLY);
 190                        if (fd < 0)
 191                                continue;
 192                        if (read(fd, id_buf, sizeof(id_buf)) < 0) {
 193                                close(fd);
 194                                continue;
 195                        }
 196                        close(fd);
 197                        id = atoll(id_buf);
 198                        if (id == config) {
 199                                closedir(evt_dir);
 200                                closedir(sys_dir);
 201                                path = zalloc(sizeof(*path));
 202                                path->system = malloc(MAX_EVENT_LENGTH);
 203                                if (!path->system) {
 204                                        free(path);
 205                                        return NULL;
 206                                }
 207                                path->name = malloc(MAX_EVENT_LENGTH);
 208                                if (!path->name) {
 209                                        free(path->system);
 210                                        free(path);
 211                                        return NULL;
 212                                }
 213                                strncpy(path->system, sys_dirent.d_name,
 214                                        MAX_EVENT_LENGTH);
 215                                strncpy(path->name, evt_dirent.d_name,
 216                                        MAX_EVENT_LENGTH);
 217                                return path;
 218                        }
 219                }
 220                closedir(evt_dir);
 221        }
 222
 223        closedir(sys_dir);
 224        return NULL;
 225}
 226
 227#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
 228static const char *tracepoint_id_to_name(u64 config)
 229{
 230        static char buf[TP_PATH_LEN];
 231        struct tracepoint_path *path;
 232
 233        path = tracepoint_id_to_path(config);
 234        if (path) {
 235                snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
 236                free(path->name);
 237                free(path->system);
 238                free(path);
 239        } else
 240                snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
 241
 242        return buf;
 243}
 244
 245static int is_cache_op_valid(u8 cache_type, u8 cache_op)
 246{
 247        if (hw_cache_stat[cache_type] & COP(cache_op))
 248                return 1;       /* valid */
 249        else
 250                return 0;       /* invalid */
 251}
 252
 253static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
 254{
 255        static char name[50];
 256
 257        if (cache_result) {
 258                sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
 259                        hw_cache_op[cache_op][0],
 260                        hw_cache_result[cache_result][0]);
 261        } else {
 262                sprintf(name, "%s-%s", hw_cache[cache_type][0],
 263                        hw_cache_op[cache_op][1]);
 264        }
 265
 266        return name;
 267}
 268
 269const char *event_name(int counter)
 270{
 271        u64 config = attrs[counter].config;
 272        int type = attrs[counter].type;
 273
 274        return __event_name(type, config);
 275}
 276
 277const char *__event_name(int type, u64 config)
 278{
 279        static char buf[32];
 280
 281        if (type == PERF_TYPE_RAW) {
 282                sprintf(buf, "raw 0x%llx", config);
 283                return buf;
 284        }
 285
 286        switch (type) {
 287        case PERF_TYPE_HARDWARE:
 288                if (config < PERF_COUNT_HW_MAX)
 289                        return hw_event_names[config];
 290                return "unknown-hardware";
 291
 292        case PERF_TYPE_HW_CACHE: {
 293                u8 cache_type, cache_op, cache_result;
 294
 295                cache_type   = (config >>  0) & 0xff;
 296                if (cache_type > PERF_COUNT_HW_CACHE_MAX)
 297                        return "unknown-ext-hardware-cache-type";
 298
 299                cache_op     = (config >>  8) & 0xff;
 300                if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
 301                        return "unknown-ext-hardware-cache-op";
 302
 303                cache_result = (config >> 16) & 0xff;
 304                if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
 305                        return "unknown-ext-hardware-cache-result";
 306
 307                if (!is_cache_op_valid(cache_type, cache_op))
 308                        return "invalid-cache";
 309
 310                return event_cache_name(cache_type, cache_op, cache_result);
 311        }
 312
 313        case PERF_TYPE_SOFTWARE:
 314                if (config < PERF_COUNT_SW_MAX)
 315                        return sw_event_names[config];
 316                return "unknown-software";
 317
 318        case PERF_TYPE_TRACEPOINT:
 319                return tracepoint_id_to_name(config);
 320
 321        default:
 322                break;
 323        }
 324
 325        return "unknown";
 326}
 327
 328static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
 329{
 330        int i, j;
 331        int n, longest = -1;
 332
 333        for (i = 0; i < size; i++) {
 334                for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
 335                        n = strlen(names[i][j]);
 336                        if (n > longest && !strncasecmp(*str, names[i][j], n))
 337                                longest = n;
 338                }
 339                if (longest > 0) {
 340                        *str += longest;
 341                        return i;
 342                }
 343        }
 344
 345        return -1;
 346}
 347
 348static enum event_result
 349parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
 350{
 351        const char *s = *str;
 352        int cache_type = -1, cache_op = -1, cache_result = -1;
 353
 354        cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
 355        /*
 356         * No fallback - if we cannot get a clear cache type
 357         * then bail out:
 358         */
 359        if (cache_type == -1)
 360                return EVT_FAILED;
 361
 362        while ((cache_op == -1 || cache_result == -1) && *s == '-') {
 363                ++s;
 364
 365                if (cache_op == -1) {
 366                        cache_op = parse_aliases(&s, hw_cache_op,
 367                                                PERF_COUNT_HW_CACHE_OP_MAX);
 368                        if (cache_op >= 0) {
 369                                if (!is_cache_op_valid(cache_type, cache_op))
 370                                        return 0;
 371                                continue;
 372                        }
 373                }
 374
 375                if (cache_result == -1) {
 376                        cache_result = parse_aliases(&s, hw_cache_result,
 377                                                PERF_COUNT_HW_CACHE_RESULT_MAX);
 378                        if (cache_result >= 0)
 379                                continue;
 380                }
 381
 382                /*
 383                 * Can't parse this as a cache op or result, so back up
 384                 * to the '-'.
 385                 */
 386                --s;
 387                break;
 388        }
 389
 390        /*
 391         * Fall back to reads:
 392         */
 393        if (cache_op == -1)
 394                cache_op = PERF_COUNT_HW_CACHE_OP_READ;
 395
 396        /*
 397         * Fall back to accesses:
 398         */
 399        if (cache_result == -1)
 400                cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
 401
 402        attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
 403        attr->type = PERF_TYPE_HW_CACHE;
 404
 405        *str = s;
 406        return EVT_HANDLED;
 407}
 408
 409static enum event_result
 410parse_single_tracepoint_event(char *sys_name,
 411                              const char *evt_name,
 412                              unsigned int evt_length,
 413                              struct perf_event_attr *attr,
 414                              const char **strp)
 415{
 416        char evt_path[MAXPATHLEN];
 417        char id_buf[4];
 418        u64 id;
 419        int fd;
 420
 421        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
 422                 sys_name, evt_name);
 423
 424        fd = open(evt_path, O_RDONLY);
 425        if (fd < 0)
 426                return EVT_FAILED;
 427
 428        if (read(fd, id_buf, sizeof(id_buf)) < 0) {
 429                close(fd);
 430                return EVT_FAILED;
 431        }
 432
 433        close(fd);
 434        id = atoll(id_buf);
 435        attr->config = id;
 436        attr->type = PERF_TYPE_TRACEPOINT;
 437        *strp = evt_name + evt_length;
 438
 439        attr->sample_type |= PERF_SAMPLE_RAW;
 440        attr->sample_type |= PERF_SAMPLE_TIME;
 441        attr->sample_type |= PERF_SAMPLE_CPU;
 442
 443        attr->sample_period = 1;
 444
 445
 446        return EVT_HANDLED;
 447}
 448
 449/* sys + ':' + event + ':' + flags*/
 450#define MAX_EVOPT_LEN   (MAX_EVENT_LENGTH * 2 + 2 + 128)
 451static enum event_result
 452parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
 453                                char *flags)
 454{
 455        char evt_path[MAXPATHLEN];
 456        struct dirent *evt_ent;
 457        DIR *evt_dir;
 458
 459        snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
 460        evt_dir = opendir(evt_path);
 461
 462        if (!evt_dir) {
 463                perror("Can't open event dir");
 464                return EVT_FAILED;
 465        }
 466
 467        while ((evt_ent = readdir(evt_dir))) {
 468                char event_opt[MAX_EVOPT_LEN + 1];
 469                int len;
 470
 471                if (!strcmp(evt_ent->d_name, ".")
 472                    || !strcmp(evt_ent->d_name, "..")
 473                    || !strcmp(evt_ent->d_name, "enable")
 474                    || !strcmp(evt_ent->d_name, "filter"))
 475                        continue;
 476
 477                if (!strglobmatch(evt_ent->d_name, evt_exp))
 478                        continue;
 479
 480                len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
 481                               evt_ent->d_name, flags ? ":" : "",
 482                               flags ?: "");
 483                if (len < 0)
 484                        return EVT_FAILED;
 485
 486                if (parse_events(NULL, event_opt, 0))
 487                        return EVT_FAILED;
 488        }
 489
 490        return EVT_HANDLED_ALL;
 491}
 492
 493
 494static enum event_result parse_tracepoint_event(const char **strp,
 495                                    struct perf_event_attr *attr)
 496{
 497        const char *evt_name;
 498        char *flags;
 499        char sys_name[MAX_EVENT_LENGTH];
 500        unsigned int sys_length, evt_length;
 501
 502        if (debugfs_valid_mountpoint(debugfs_path))
 503                return 0;
 504
 505        evt_name = strchr(*strp, ':');
 506        if (!evt_name)
 507                return EVT_FAILED;
 508
 509        sys_length = evt_name - *strp;
 510        if (sys_length >= MAX_EVENT_LENGTH)
 511                return 0;
 512
 513        strncpy(sys_name, *strp, sys_length);
 514        sys_name[sys_length] = '\0';
 515        evt_name = evt_name + 1;
 516
 517        flags = strchr(evt_name, ':');
 518        if (flags) {
 519                /* split it out: */
 520                evt_name = strndup(evt_name, flags - evt_name);
 521                flags++;
 522        }
 523
 524        evt_length = strlen(evt_name);
 525        if (evt_length >= MAX_EVENT_LENGTH)
 526                return EVT_FAILED;
 527
 528        if (strpbrk(evt_name, "*?")) {
 529                *strp = evt_name + evt_length;
 530                return parse_multiple_tracepoint_event(sys_name, evt_name,
 531                                                       flags);
 532        } else
 533                return parse_single_tracepoint_event(sys_name, evt_name,
 534                                                     evt_length, attr, strp);
 535}
 536
 537static enum event_result
 538parse_breakpoint_type(const char *type, const char **strp,
 539                      struct perf_event_attr *attr)
 540{
 541        int i;
 542
 543        for (i = 0; i < 3; i++) {
 544                if (!type[i])
 545                        break;
 546
 547                switch (type[i]) {
 548                case 'r':
 549                        attr->bp_type |= HW_BREAKPOINT_R;
 550                        break;
 551                case 'w':
 552                        attr->bp_type |= HW_BREAKPOINT_W;
 553                        break;
 554                case 'x':
 555                        attr->bp_type |= HW_BREAKPOINT_X;
 556                        break;
 557                default:
 558                        return EVT_FAILED;
 559                }
 560        }
 561        if (!attr->bp_type) /* Default */
 562                attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
 563
 564        *strp = type + i;
 565
 566        return EVT_HANDLED;
 567}
 568
 569static enum event_result
 570parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
 571{
 572        const char *target;
 573        const char *type;
 574        char *endaddr;
 575        u64 addr;
 576        enum event_result err;
 577
 578        target = strchr(*strp, ':');
 579        if (!target)
 580                return EVT_FAILED;
 581
 582        if (strncmp(*strp, "mem", target - *strp) != 0)
 583                return EVT_FAILED;
 584
 585        target++;
 586
 587        addr = strtoull(target, &endaddr, 0);
 588        if (target == endaddr)
 589                return EVT_FAILED;
 590
 591        attr->bp_addr = addr;
 592        *strp = endaddr;
 593
 594        type = strchr(target, ':');
 595
 596        /* If no type is defined, just rw as default */
 597        if (!type) {
 598                attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
 599        } else {
 600                err = parse_breakpoint_type(++type, strp, attr);
 601                if (err == EVT_FAILED)
 602                        return EVT_FAILED;
 603        }
 604
 605        /* We should find a nice way to override the access type */
 606        attr->bp_len = HW_BREAKPOINT_LEN_4;
 607        attr->type = PERF_TYPE_BREAKPOINT;
 608
 609        return EVT_HANDLED;
 610}
 611
 612static int check_events(const char *str, unsigned int i)
 613{
 614        int n;
 615
 616        n = strlen(event_symbols[i].symbol);
 617        if (!strncmp(str, event_symbols[i].symbol, n))
 618                return n;
 619
 620        n = strlen(event_symbols[i].alias);
 621        if (n)
 622                if (!strncmp(str, event_symbols[i].alias, n))
 623                        return n;
 624        return 0;
 625}
 626
 627static enum event_result
 628parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
 629{
 630        const char *str = *strp;
 631        unsigned int i;
 632        int n;
 633
 634        for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
 635                n = check_events(str, i);
 636                if (n > 0) {
 637                        attr->type = event_symbols[i].type;
 638                        attr->config = event_symbols[i].config;
 639                        *strp = str + n;
 640                        return EVT_HANDLED;
 641                }
 642        }
 643        return EVT_FAILED;
 644}
 645
 646static enum event_result
 647parse_raw_event(const char **strp, struct perf_event_attr *attr)
 648{
 649        const char *str = *strp;
 650        u64 config;
 651        int n;
 652
 653        if (*str != 'r')
 654                return EVT_FAILED;
 655        n = hex2u64(str + 1, &config);
 656        if (n > 0) {
 657                *strp = str + n + 1;
 658                attr->type = PERF_TYPE_RAW;
 659                attr->config = config;
 660                return EVT_HANDLED;
 661        }
 662        return EVT_FAILED;
 663}
 664
 665static enum event_result
 666parse_numeric_event(const char **strp, struct perf_event_attr *attr)
 667{
 668        const char *str = *strp;
 669        char *endp;
 670        unsigned long type;
 671        u64 config;
 672
 673        type = strtoul(str, &endp, 0);
 674        if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
 675                str = endp + 1;
 676                config = strtoul(str, &endp, 0);
 677                if (endp > str) {
 678                        attr->type = type;
 679                        attr->config = config;
 680                        *strp = endp;
 681                        return EVT_HANDLED;
 682                }
 683        }
 684        return EVT_FAILED;
 685}
 686
 687static enum event_result
 688parse_event_modifier(const char **strp, struct perf_event_attr *attr)
 689{
 690        const char *str = *strp;
 691        int exclude = 0;
 692        int eu = 0, ek = 0, eh = 0, precise = 0;
 693
 694        if (*str++ != ':')
 695                return 0;
 696        while (*str) {
 697                if (*str == 'u') {
 698                        if (!exclude)
 699                                exclude = eu = ek = eh = 1;
 700                        eu = 0;
 701                } else if (*str == 'k') {
 702                        if (!exclude)
 703                                exclude = eu = ek = eh = 1;
 704                        ek = 0;
 705                } else if (*str == 'h') {
 706                        if (!exclude)
 707                                exclude = eu = ek = eh = 1;
 708                        eh = 0;
 709                } else if (*str == 'p') {
 710                        precise++;
 711                } else
 712                        break;
 713
 714                ++str;
 715        }
 716        if (str >= *strp + 2) {
 717                *strp = str;
 718                attr->exclude_user   = eu;
 719                attr->exclude_kernel = ek;
 720                attr->exclude_hv     = eh;
 721                attr->precise_ip     = precise;
 722                return 1;
 723        }
 724        return 0;
 725}
 726
 727/*
 728 * Each event can have multiple symbolic names.
 729 * Symbolic names are (almost) exactly matched.
 730 */
 731static enum event_result
 732parse_event_symbols(const char **str, struct perf_event_attr *attr)
 733{
 734        enum event_result ret;
 735
 736        ret = parse_tracepoint_event(str, attr);
 737        if (ret != EVT_FAILED)
 738                goto modifier;
 739
 740        ret = parse_raw_event(str, attr);
 741        if (ret != EVT_FAILED)
 742                goto modifier;
 743
 744        ret = parse_numeric_event(str, attr);
 745        if (ret != EVT_FAILED)
 746                goto modifier;
 747
 748        ret = parse_symbolic_event(str, attr);
 749        if (ret != EVT_FAILED)
 750                goto modifier;
 751
 752        ret = parse_generic_hw_event(str, attr);
 753        if (ret != EVT_FAILED)
 754                goto modifier;
 755
 756        ret = parse_breakpoint_event(str, attr);
 757        if (ret != EVT_FAILED)
 758                goto modifier;
 759
 760        fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
 761        fprintf(stderr, "Run 'perf list' for a list of valid events\n");
 762        return EVT_FAILED;
 763
 764modifier:
 765        parse_event_modifier(str, attr);
 766
 767        return ret;
 768}
 769
 770static int store_event_type(const char *orgname)
 771{
 772        char filename[PATH_MAX], *c;
 773        FILE *file;
 774        int id, n;
 775
 776        sprintf(filename, "%s/", debugfs_path);
 777        strncat(filename, orgname, strlen(orgname));
 778        strcat(filename, "/id");
 779
 780        c = strchr(filename, ':');
 781        if (c)
 782                *c = '/';
 783
 784        file = fopen(filename, "r");
 785        if (!file)
 786                return 0;
 787        n = fscanf(file, "%i", &id);
 788        fclose(file);
 789        if (n < 1) {
 790                pr_err("cannot store event ID\n");
 791                return -EINVAL;
 792        }
 793        return perf_header__push_event(id, orgname);
 794}
 795
 796int parse_events(const struct option *opt __used, const char *str, int unset __used)
 797{
 798        struct perf_event_attr attr;
 799        enum event_result ret;
 800
 801        if (strchr(str, ':'))
 802                if (store_event_type(str) < 0)
 803                        return -1;
 804
 805        for (;;) {
 806                if (nr_counters == MAX_COUNTERS)
 807                        return -1;
 808
 809                memset(&attr, 0, sizeof(attr));
 810                ret = parse_event_symbols(&str, &attr);
 811                if (ret == EVT_FAILED)
 812                        return -1;
 813
 814                if (!(*str == 0 || *str == ',' || isspace(*str)))
 815                        return -1;
 816
 817                if (ret != EVT_HANDLED_ALL) {
 818                        attrs[nr_counters] = attr;
 819                        nr_counters++;
 820                }
 821
 822                if (*str == 0)
 823                        break;
 824                if (*str == ',')
 825                        ++str;
 826                while (isspace(*str))
 827                        ++str;
 828        }
 829
 830        return 0;
 831}
 832
 833int parse_filter(const struct option *opt __used, const char *str,
 834                 int unset __used)
 835{
 836        int i = nr_counters - 1;
 837        int len = strlen(str);
 838
 839        if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
 840                fprintf(stderr,
 841                        "-F option should follow a -e tracepoint option\n");
 842                return -1;
 843        }
 844
 845        filters[i] = malloc(len + 1);
 846        if (!filters[i]) {
 847                fprintf(stderr, "not enough memory to hold filter string\n");
 848                return -1;
 849        }
 850        strcpy(filters[i], str);
 851
 852        return 0;
 853}
 854
 855static const char * const event_type_descriptors[] = {
 856        "Hardware event",
 857        "Software event",
 858        "Tracepoint event",
 859        "Hardware cache event",
 860        "Raw hardware event descriptor",
 861        "Hardware breakpoint",
 862};
 863
 864/*
 865 * Print the events from <debugfs_mount_point>/tracing/events
 866 */
 867
 868static void print_tracepoint_events(void)
 869{
 870        DIR *sys_dir, *evt_dir;
 871        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 872        char evt_path[MAXPATHLEN];
 873        char dir_path[MAXPATHLEN];
 874
 875        if (debugfs_valid_mountpoint(debugfs_path))
 876                return;
 877
 878        sys_dir = opendir(debugfs_path);
 879        if (!sys_dir)
 880                return;
 881
 882        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 883
 884                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 885                         sys_dirent.d_name);
 886                evt_dir = opendir(dir_path);
 887                if (!evt_dir)
 888                        continue;
 889
 890                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 891                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
 892                                 sys_dirent.d_name, evt_dirent.d_name);
 893                        printf("  %-42s [%s]\n", evt_path,
 894                                event_type_descriptors[PERF_TYPE_TRACEPOINT]);
 895                }
 896                closedir(evt_dir);
 897        }
 898        closedir(sys_dir);
 899}
 900
 901/*
 902 * Print the help text for the event symbols:
 903 */
 904void print_events(void)
 905{
 906        struct event_symbol *syms = event_symbols;
 907        unsigned int i, type, op, prev_type = -1;
 908        char name[40];
 909
 910        printf("\n");
 911        printf("List of pre-defined events (to be used in -e):\n");
 912
 913        for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
 914                type = syms->type;
 915
 916                if (type != prev_type)
 917                        printf("\n");
 918
 919                if (strlen(syms->alias))
 920                        sprintf(name, "%s OR %s", syms->symbol, syms->alias);
 921                else
 922                        strcpy(name, syms->symbol);
 923                printf("  %-42s [%s]\n", name,
 924                        event_type_descriptors[type]);
 925
 926                prev_type = type;
 927        }
 928
 929        printf("\n");
 930        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
 931                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
 932                        /* skip invalid cache type */
 933                        if (!is_cache_op_valid(type, op))
 934                                continue;
 935
 936                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
 937                                printf("  %-42s [%s]\n",
 938                                        event_cache_name(type, op, i),
 939                                        event_type_descriptors[PERF_TYPE_HW_CACHE]);
 940                        }
 941                }
 942        }
 943
 944        printf("\n");
 945        printf("  %-42s [%s]\n",
 946                "rNNN (see 'perf list --help' on how to encode it)",
 947               event_type_descriptors[PERF_TYPE_RAW]);
 948        printf("\n");
 949
 950        printf("  %-42s [%s]\n",
 951                        "mem:<addr>[:access]",
 952                        event_type_descriptors[PERF_TYPE_BREAKPOINT]);
 953        printf("\n");
 954
 955        print_tracepoint_events();
 956
 957        exit(129);
 958}
 959
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.